tracker issue : CF-4203280

select a category, or use search below
(searches all categories and all time range)
Title:

[ANeff] Bug for: unscopable variables create closure vulnerability

| View in Tracker

Status/Resolution/Reason: To Fix//EnhancementRequired

Reporter/Name(from Bugbase): Aaron Neff / ()

Created: 08/17/2018

Components: Language, Closures

Versions: 13.0

Failure Type: Enhancement Request

Found In Build/Fixed In Build: 2018.0.0.310739 /

Priority/Frequency: Normal / Some users will encounter

Locale/System: / Platforms All

Vote Count: 0

Issue: unscopable variables create closure vulnerability

Example 1:
-----------
function function set2D(numeric xAxis=0, numeric yAxis=0) {
  return function(numeric zAxis=0) {
    return "(#xAxis#,#yAxis#,#ARGUMENTS.zAxis#)"
  }
}
get3D=set2D(xAxis=1, yAxis=2)
get3D(xAxis=3)//typo: 'x' should be 'z'
-----------

Issue 1: If innocent user makes a typo and calls `get3D(xAxis=3)`, instead of `get3D(zAxis=3)`, there is silent corruption.

Example 2 (where isPrivileged() and secretNumberGenerator() were converted to java bytecode via cfcompile's Sourceless Distribution):
-----------
//Begin sourceless distributed code
boolean function isPrivileged() {return false}//pseudo code for illustration
function function secretNumberGenerator() {
  var isPrivileged = isPrivileged()
  return function() {return isPrivileged ? randRange(1,1000) : 0}
}
//End sourceless distributed code
getSecretNumber=secretNumberGenerator()
writeOutput(getSecretNumber(isPrivileged=true))//hacker discovers and exploits unscoped variable named isPrivileged
-----------

Issue 2: Hackers can discover unscoped variable names in sourceless-deployed closures by passing arbitrary arguments when calling the closure.

Enhancement Request 1: New function-local scopes 'OWNERARGUMENTS' and 'OWNERLOCAL', allowing child functions to scope references to variables in owner function's scopes. This would also allow callbacks (ex: array.map(callback)) to scope their references to variables in the owner function's scopes without hacky workarounds.

Then both closure return statements could be rewritten:
- Example 1: `return "(#OWNERARGUMENTS.xAxis#,#OWNERARGUMENTS.yAxis#,#ARGUMENTS.zAxis#)"`
- Example 2: `return OWNERLOCAL.isPrivileged ? randRange(1,1000) : 0`

However, hackers could still discover/exploit unscoped variables by passing arbitrary keys in a OWNERLOCAL struct.
- Example 2: `writeOutput(getSecretNumber(OWNERLOCAL={isPrivileged=true}))`

Enhancement Request 2: Per-app setting THIS.enableScopeShadowing=true(default)|false. THIS.enableScopeShadowing=false would disable CF's scope shadowing and, thus, prevent hackers from working around Enhancement Request 1.

Related URL: https://docs.lucee.org/guides/developing-with-lucee-server/language-syntax-differences.html#scope-names-cannot-be-overwritten

Attachments:

Comments: