fix($parse): disallow passing Function to Array.sort

Fix the following exploit:

    hasOwnProperty.constructor.prototype.valueOf = valueOf.call;
    ["a", "alert(1)"].sort(hasOwnProperty.constructor);

The exploit:
• 1. Array.sort takes a comparison function and passes it 2 parameters to compare.
  2. It then calls .valueOf() if the result is not a primitive.
• The Function object conveniently accepts two string arguments so we can use this
  to construct a function.  However, this doesn't do much unless we can execute it.
• We set the valueOf function on Function.prototype to Function.prototype.call.
  This causes the function that we constructed to be executed when sort calls
  .valueOf() on the result of the comparison.

The fix is in two parts.
• Disallow passing unsafe objects to function calls as parameters.
• Do not traverse the Function object when setting a path.
This commit is contained in:
Chirayu Krishnappa
2014-09-08 16:27:26 -07:00
committed by Brian Ford
parent 6639ca9d6b
commit bd8ad0fbe8
2 changed files with 40 additions and 3 deletions

View File

@@ -747,7 +747,7 @@ Parser.prototype = {
if (args) {
var i = argsFn.length;
while (i--) {
args[i] = argsFn[i](scope, locals);
args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);
}
}
@@ -835,11 +835,12 @@ Parser.prototype = {
//////////////////////////////////////////////////
function setter(obj, path, setValue, fullExp) {
ensureSafeObject(obj, fullExp);
var element = path.split('.'), key;
for (var i = 0; element.length > 1; i++) {
key = ensureSafeMemberName(element.shift(), fullExp);
var propertyObj = obj[key];
var propertyObj = ensureSafeObject(obj[key], fullExp);
if (!propertyObj) {
propertyObj = {};
obj[key] = propertyObj;
@@ -847,7 +848,6 @@ function setter(obj, path, setValue, fullExp) {
obj = propertyObj;
}
key = ensureSafeMemberName(element.shift(), fullExp);
ensureSafeObject(obj, fullExp);
ensureSafeObject(obj[key], fullExp);
obj[key] = setValue;
return setValue;