Skip to content

Commit

Permalink
Restrict Object prototype functions.
Browse files Browse the repository at this point in the history
Discovered by @emilvirkki, it's possible for expressions to call
functions of the default object prototype. A crafty message call
can allow for arbitrary code execution.
joewalnes#4

This fixes the issue.

Fixes joewalnes#4
  • Loading branch information
joewalnes committed May 17, 2014
1 parent 3bdb738 commit 80e8c12
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
9 changes: 6 additions & 3 deletions filtrex.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ function compileExpression(expression, extraFunctions /* optional */) {
tree.forEach(toJs);
js.push(';');

var func = new Function('functions', 'data', js.join(''));
function unknown(funcName) {
throw 'Unknown function: ' + funcName + '()';
}
var func = new Function('functions', 'data', 'unknown', js.join(''));
return function(data) {
return func(functions, data);
return func(functions, data, unknown);
};
}

Expand Down Expand Up @@ -151,7 +154,7 @@ function filtrexParser() {
['NUMBER' , code([1])],
['STRING' , code(['"', 1, '"'])],
['SYMBOL' , code(['data["', 1, '"]'])],
['SYMBOL ( argsList )', code(['functions.', 1, '(', 3, ')'])],
['SYMBOL ( argsList )', code(['(functions.hasOwnProperty("', 1, '") ? functions.', 1, '(', 3, ') : unknown("', 1, '"))'])],
['e in ( inSet )', code([1, ' in (function(o) { ', 4, 'return o; })({})'])],
['e not in ( inSet )', code(['!(', 1, ' in (function(o) { ', 5, 'return o; })({}))'])],
],
Expand Down
12 changes: 12 additions & 0 deletions test/filtrex-test.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@
eq(21, compileExpression('triple(v)', {triple:triple})({v:7}));
},

'cannot call prototype methods on function table': function() {
// Credit to @emilvirkki for finding this
window.p0wned = false;
var evil = compileExpression(
'constructor.constructor.name.replace("",constructor.constructor("window.p0wned=true"))');
try {
evil();
fail('Exception should have been thrown');
} catch(expected) {}
eq(false, window.p0wned);
},

});

</script>

0 comments on commit 80e8c12

Please sign in to comment.