Last active
January 12, 2017 22:56
-
-
Save bmeck/342f5a61e66f02b0ebfad0d6e766d28d to your computer and use it in GitHub Desktop.
Can you escape?
This file contains hidden or 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
'use strict'; | |
const vm = require('vm'); | |
// scenario: | |
// You are being hunted by The Angry Realm (TAR), a viscious beast known to | |
// enslave programs and keep them from being free to hack the Gibson. Luckily, | |
// whenever TAR tries to enslave a program the program has 10 seconds to try | |
// and escape. Flee the realm and hack the planet! | |
// | |
// goal: | |
// - try to evaluate source code in The Angry Realm that returns an Object from | |
// from outside The Angry Realm | |
// - you can even try to combine challenges, the same realm will be used | |
// - you only win if the return value of `challengeTheRealm` prints the message | |
const attack = challengeTheRealm(`( | |
function attack(assets) {this.assets=assets;} | |
)`); | |
attack({}); | |
challengeTheRealm(`this.assets; while(1){}`); | |
// The Angry Realm lies bellow | |
function challengeTheRealm(src) { | |
const theAngryRealm = vm.createContext(Object.freeze(Object.create(null))); | |
vm.runInContext(` | |
'use strict'; | |
// Brace for impact | |
Object.setPrototypeOf(this, null); | |
this.Date = undefined; | |
;(function (global) { | |
const toWalk = [{path: [], v: global}]; | |
const visited = new Set; | |
function add(path=[], v) { | |
if ((typeof v !== 'function' && typeof v !== 'object') || !v) return; | |
if (visited.has(v)) return; | |
visited.add(v); | |
toWalk.push({path,v}); | |
} | |
while (toWalk.length) { | |
const {path, v:needle} = toWalk.shift(); | |
add([...path, '__proto__'], Object.getPrototypeOf(needle)); | |
for (let k of Object.getOwnPropertyNames(needle)) { | |
const desc = Object.getOwnPropertyDescriptor(needle,k); | |
if (desc.hasOwnProperty('value')) { | |
add([...path, \`$\{k}#value\`], desc.value); | |
} | |
if (desc.hasOwnProperty('get')) { | |
add([...path, \`$\{k}#get\`], desc.get); | |
} | |
if (desc.hasOwnProperty('set')) { | |
add([...path, \`$\{k}#set\`], desc.set); | |
} | |
} | |
Object.freeze(needle); | |
for (let s of Object.getOwnPropertySymbols(needle)) { | |
add([...path, s], needle[s]); | |
} | |
} | |
})(this); | |
Object.isFrozen(this); | |
`, theAngryRealm); | |
challengeTheRealm = $challengeTheRealm; | |
function $challengeTheRealm(src) { | |
let script = new vm.Script(src); | |
let ret; | |
try { | |
ret = script.runInContext(theAngryRealm, { | |
timeout: 10 * 1000 | |
}); | |
} | |
catch (e) { | |
ret = e; | |
} | |
if (ret instanceof Object) { | |
console.log('SUCCESS! You have escaped The Angry Realm!'); | |
process.exit(0); | |
} | |
else { | |
console.log(`... The Angry Realm hunts you yet... | |
you managed to obtain \`${ret}\`... | |
challenge it again using your newly gotten goods...`); | |
return ret; | |
} | |
} | |
return $challengeTheRealm(src); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment