Created
March 27, 2019 22:04
-
-
Save roddux/866c95fbb7317cc87f69d271f0d36c54 to your computer and use it in GitHub Desktop.
In-process JS builtin fuzzing idea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Inspiration: @5aelo, @_tsuro, @ifsecure, @bkth_ | |
// $ ./spidermonkey/js ./fuck^H^Hzz.js | |
// A quick thought experiment. A simple in-process template fuzzer using eval. | |
// Next idea is to generate the template, too. This one was hardcoded to try and find JIT bugs. Perhaps it will, I only ran it for a few hours. | |
// Can code even be JIT'd if it's being run via eval, though? Idk. Baby steps. | |
var rc = (x)=>x[Math.floor(Math.random() * x.length)]; | |
var _object = [ | |
"Object()", "{}", "{1:1,2:2,3:3,4:4,5:5}", "{a:1,b:2,c:3,d:4,e:5}", | |
"Array()", "[]", "Array(10)", "[1,2,3,4,5]", "[1.1,2.2,3.3,4.4,5.5]" | |
]; | |
var _objarg = ["arg1","arg2"]; | |
var _malobject = [ "{}" ]; | |
var _prop = [ // Stolen from domato | |
"1", "'1'", "{}", "[]", "undefined", "null", "32768", "65535", "65536", "1073741824", | |
"536870912", "268435456","4294967295", "2147483648", "2147483647", "-2147483648", "-1073741824", "-32769" | |
]; | |
var _propline = [ | |
"<arg>[1] = <prop>;", | |
"<arg>['a'] = <prop>;", | |
"<arg>.a = <prop>;", | |
"let _=<arg>[0];" | |
]; | |
var _builtin = [ | |
"Array.prototype.join.apply( <arg>, [ <element> ] )", | |
"Array.prototype.toLocaleString.apply( <arg> )", | |
"Array.prototype.reverse.apply( <arg> )", | |
"Array.prototype.push.apply( <arg>, [ <element> ] )", | |
"Array.prototype.pop.apply( <arg> )", | |
"Array.prototype.shift.apply( <arg> )", | |
"Array.prototype.unshift.apply( <arg>, [ <element> ] )", | |
"Array.prototype.splice.apply( <arg>, [ <number> ] )", | |
"Array.prototype.splice.apply( <arg>, [ <number>, <number> ] )", | |
"Array.prototype.toSource.apply( <arg> )", | |
"Array.prototype.slice.apply( <arg> )", | |
"Array.prototype.slice.apply( <arg>, [ <number>, <number> ] )", | |
"Array.of( <element> )", | |
"Array.isArray( <element> )", | |
"Object.prototype.toSource.apply( <arg> )", | |
"Object.prototype.toString.apply( <arg> )", | |
"Object.prototype.isPrototypeOf.apply( <arg>, [ <arg> ] )", | |
"Object.prototype.propertyIsEnumerable.apply( <arg>, [ <propertyName> ] )", | |
"Object.assign( <arg>, <arg> )", | |
"Object.setPrototypeOf( <arg>, <arg> )", | |
"Object.keys( <arg> )", | |
"Object.values( <arg> )", | |
"Object.entries( <arg> )", | |
"Object.is( <arg>, <arg> )", | |
"Object.defineProperties( <arg>, <propertyDefinition> )", | |
"Object.create( <arg> )", | |
"Object.create( <arg>, <propertyDefinition> )", | |
"Object.getOwnPropertyNames( <arg> )", | |
"Object.getOwnPropertySymbols( <arg> )", | |
"Object.preventExtensions( <arg> )", | |
"Object.freeze( <arg> )", | |
"Object.isFrozen( <arg> )", | |
"Object.seal( <arg> )", | |
]; | |
var tmpl = ` | |
var a1 = <object>, a2 = <object>; | |
var p1 = <malobject>, p2 = <malobject>; | |
var flip = false; | |
var handle2 = { | |
get: function(target, prop, receiver) { | |
if ( flip ) { | |
a1.a = <prop>; a1[0] = <prop>; | |
} else { | |
return Reflect.get(...arguments); | |
} | |
} | |
}; | |
var p1 = new Proxy(a1, handle2); | |
function opt(arg1, arg2) { | |
function inline(arg1) { | |
<builtin> | |
} | |
for(let _=0;_<1e2;_++,inline(arg1)); | |
<propline> | |
if ( flip ) <builtin>; | |
} | |
for(var i=0;i<1e4;i++){ opt(a1, a2); } | |
flip = true; | |
a1.a = <prop>; | |
opt(a1,{}); | |
a1.a = <prop>; | |
opt(p1,{}); | |
`; | |
// let gc = () => for(j=0;j<10;q = new WebAssembly.Memory({initial: 16384})); | |
var tags = { | |
"<object>": _object, | |
"<prop>": _prop, | |
"<arg>": _objarg, | |
"<element>": [NaN,"'abc'",Infinity,0,-1], | |
"<number>": [1,2,3,4,5,6,7,8,9,0], | |
"<malobject>": _malobject, | |
"<propline>": _propline, | |
"<builtin>": _builtin, | |
"<propertyDefinition>": ["{}"], | |
"<propertyName>": ["'length'"], | |
}; | |
function process(template) { | |
function toReplace() { | |
let instances = 0; | |
Object.keys(tags).forEach( | |
function (tag) { | |
// cheers, rebecca | |
instances += (template.match(RegExp(tag,"g")) || []).length; | |
} | |
); | |
return instances; | |
} | |
let ic = toReplace(); | |
while (ic > 0) { | |
Object.keys(tags).forEach( | |
function(tag) { | |
while ( template.indexOf(tag) != -1 ) { | |
template = template.replace(tag, rc(tags[tag])); | |
} | |
} | |
); | |
ic = toReplace(); | |
} | |
return template; | |
} | |
console.log("[*] Entering fuzzing loop"); | |
var tnum = 0; | |
while(true) { | |
console.log("[*] Preparing template", tnum); | |
let exec = process(tmpl); | |
console.log("[*] Displaying template"); | |
console.log(exec); | |
console.log("[*] Executing template"); | |
try { | |
eval(exec); | |
} catch(e) { | |
console.log("[!] Caught exception"); | |
console.log(e); | |
} | |
console.log("[*] Completed fuzzing run"); | |
tnum += 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment