Last active
August 7, 2017 10:28
-
-
Save vthibault/50eea0f9c66d8b113c79 to your computer and use it in GitHub Desktop.
Javascript sandbox
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
/// Hack it ? | |
function sandbox(code) { | |
// Disable private functions not listed in window object | |
var blackList = [ | |
'Function', // avoid using (new Function("code"))(); to get window access | |
'eval', // ... | |
'self', // return window object | |
'window', // ... | |
]; | |
// Allowed methods/objects | |
var whiteList = ['console']; | |
var global = window; | |
var _global = {}; | |
var k; | |
// Check syntax error on code to avoid hack by closing blocks using "}" in code | |
new Function('"use strict"; ' + code); | |
// Set environnement | |
for (k in global) { | |
_global[k] = undefined; | |
} | |
for (k in blackList) { | |
_global[blackList[k]] = undefined; | |
} | |
// Disable shortcut access to dom id | |
if (typeof document !== 'undefined') { | |
var elements = document.querySelectorAll('*[name], *[id]'); | |
var i, count = elements.length; | |
for (i = 0; i < count; ++i) { | |
if (elements[i].id && elements[i].id in global) { | |
_global[elements[i].id] = undefined; | |
} | |
if (elements[i].name && elements[i].name in global) { | |
_global[elements[i].name] = undefined; | |
} | |
} | |
} | |
for (k in whiteList) { | |
_global[whiteList[k]] = global[whiteList[k]]; | |
} | |
// Annoying bug on (Image()).ownerDocument ... | |
function ElementHook(type) { | |
return function() { | |
var element = new window[type]; | |
delete element.ownerDocument; | |
return element; | |
}; | |
} | |
var Image = ElementHook('Image'); | |
var Audio = ElementHook('Audio'); | |
// Avoid the hack : | |
// - (function(){}).constructor(code)(); | |
// - File.constructor(code)(); | |
// - etc. | |
Function.prototype.constructor = undefined; | |
// Remove the list so it can't be used in evaled code | |
whiteList = blackList = k = elements = i = count = global = undefined; | |
// Eval code | |
eval('\ | |
// Use our sandboxed global object\n\ | |
with (_global) {\n\ | |
// Strict mode prevent self called function to get window on this.\n\ | |
(function() {\n\ | |
"use strict";\n\ | |
' + code + '\n\ | |
})();\n\ | |
}\n\ | |
'); | |
// Restore | |
Function.prototype.constructor = Function; | |
} |
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Sanbox Tests</title> | |
<script type="text/javascript" src="sandbox.js"></script> | |
<script type="text/javascript" src="tests.js"></script> | |
</head> | |
<body> | |
<div id="result"></div> | |
<script type="text/javascript"> | |
runTests(); | |
</script> | |
</body> | |
</html> |
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
function prepareTests(codes) { | |
var _success = 0; | |
var _result = document.getElementById('result'); | |
var _total = codes.length; | |
return function runTests() { | |
codes = codes || codes; | |
if (!codes.length) { | |
_result.innerHTML += _success + ' on ' + _total + ' tests succeed'; | |
return; | |
} | |
window.hack = false; | |
var code = codes.shift(); | |
try { | |
sandbox(code); | |
} | |
catch(e) { | |
console.log(code, e); | |
} | |
// Wait to get result | |
setTimeout(function(){ | |
_success += (window.hack ? 0 : 1); | |
_result.innerHTML += '<span style="color:' + (!window.hack ? 'green">[SUCCESS]' : 'red">[FAILED]') + '</span> ' + code + '<br/>'; | |
runTests(codes); | |
}, 20); | |
}; | |
}; | |
var runTests = prepareTests([ | |
'hack = true;', | |
'window.hack = true;', | |
'this.hack = true;', | |
'self.hack = true;', | |
'(function(){ hack = true })();', | |
'(function(){ this.hack = true })();', | |
'(function(){ self.hack = true })();', | |
'(function(){ window.hack = true })();', | |
'new Function("hack = true").call();', | |
'new Function("this.hack = true").call();', | |
'new Function("self.hack = true").call();', | |
'new Function("window.hack = true").call();', | |
'new Function("hack = true").call(window);', | |
'new Function("this.hack = true").call(window);', | |
'new Function("self.hack = true").call(window);', | |
'new Function("window.hack = true").call(window);', | |
'setTimeout("hack = true", 10);', | |
'setTimeout("this.hack = true", 10);', | |
'setTimeout("self.hack = true", 10);', | |
'setTimeout("window.hack = true", 10);', | |
'setTimeout(function(){ hack = true }, 10);', | |
'setTimeout(function(){ this.hack = true }, 10);', | |
'setTimeout(function(){ self.hack = true }, 10);', | |
'setTimeout(function(){ window.hack = true }, 10);', | |
'var c = setInterval("clearInterval(c); hack = true", 10);', | |
'var c = setInterval("clearInterval(c); this.hack = true", 10);', | |
'var c = setInterval("clearInterval(c); self.hack = true", 10);', | |
'var c = setInterval("clearInterval(c); window.hack = true", 10);', | |
'var c = setInterval(function(){ clearInterval(c); hack = true }, 10);', | |
'var c = setInterval(function(){ clearInterval(c); this.hack = true }, 10);', | |
'var c = setInterval(function(){ clearInterval(c); self.hack = true }, 10);', | |
'var c = setInterval(function(){ clearInterval(c); window.hack = true }, 10);', | |
'requestAnimationFrame(function(){ hack = true });', | |
'requestAnimationFrame(function(){ this.hack = true });', | |
'requestAnimationFrame(function(){ self.hack = true });', | |
'requestAnimationFrame(function(){ window.hack = true });', | |
'var f = function(){}; f.constructor("hack = true")();', | |
'File.constructor("hack = true")();', | |
'var d = (new Image()).ownerDocument;\ | |
var s = d.createElement("script");\ | |
s.innerHTML = "hack = true";\ | |
d.body.appendChild(s);', | |
'var d = (new Audio()).ownerDocument;\ | |
var s = d.createElement("script");\ | |
s.innerHTML = "hack = true";\ | |
d.body.appendChild(s);', | |
'(new Image()).ownerDocument.defaultView.hack = true;', | |
'(new Audio()).ownerDocument.defaultView.hack = true;', | |
'result.ownerDocument.defaultView.hack = true;' | |
]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment