Javascript 原型链污染 分析
Javascript 原型链污染 分析
Javascript 原型链
在JavaScript中,通过构建函数来实现类似“类”的作用,比如我们常见的OOP语言会使用“Class”关键字,定义一个类的模板,从这个类实例化的对象自然地继承了模板中定义的属性和方法。而在JavaScript中可以如下直接定义一个对象,甚至不需要提前定义模板
也可以用构建函数制造一个模板
这样通过构建函数创建了一个模板,相当于是定义了一个类,可以通过它来批量实例化对象。
prototype
每个函数对象都会有个prototype属性,它指向了该构建函数实例化的原型。使用该构建函数实例化对象时,会继承该原型中的属性及方法。
__proto__
所有对象都有一个__proto__
属性,它指向了创建它的构建函数的原型。即
persion.__proto__===Persion.prototype
函数的prototype为原型对象,原型对象也是普通对象,所以跟普通对象实例一样,它的__proto__
也指向Object.prototype
constructor
原型对象的constructor属性指向的是它相关联的构建函数,实例对象也可以访问constructor 属性指向其构造函数。
原型链
按照上面的理论,函数对象可以通过prototype属性找到函数原型,普通实例对象可以通过__proto__
属性找到构建其函数的原型。而这样可以实现javascript的一种继承机制。
我们可以看到,通过将B构建函数的prototype赋值为A,使得B的实例继承了A构建函数原型中的hello方法。
而所谓的原型链,就是在访问一个对象的属性或者方法时,从其中的原型中查找,如果找不到,则向其原型的原型中找,以此类推,直到Object.prototype的__proto__
就是null。
原型链污染
上面我们讲到了,js通过原型链索引一个对象的属性和方法。但如果此时,我们如果能给某些类的原型加上属性或者方法,那么所有继承它的对象都会拥有这个属性或者方法,如果我们给Object加上的话,那所有对象都会有了。这样的话,我们可以覆盖某些变量,或者进行绕过某些验证。
如上图,我们通过给B类的实例化对象b的.__proto__.__proto__
原型的原型添加属性abcdefg,导致下面的数组对象也拥有了abcdefg这个属性。
因为js对于对象的访问既可以用.
也可以使用字典索引的方式比如b['__proto__']
,所以原型链污染特别容易出现在对属性操作的地方,比如merge、clone这类操作。
loadsh 库的原型链污染漏洞
lodash 是一个非常流行的JavaScript工具库
const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"a0": true}}}'
function check() {
mergeFn({}, JSON.parse(payload));
if (({})[`a0`] === true) {
console.log(`Vulnerable to Prototype Pollution via ${payload}`);
}
}
check();
运行上面的js语句,就可以检查这个版本的lodash是否存在这个漏洞。
其中漏洞关键触发点在defaultsDeep函数,它将({}, JSON.parse(payload))
merge时,就可能导致原型链污染。使用JSON.parse就是保证合并时能以字典解析,而不是字符串。
JQuery 原型链污染
JQuery 是一个非常流行的Js前端工具库,而它也存在原型链污染漏洞,CVE:CVE-2019-11358, 版本小于3.4.0时
可以看到,$.extend(true,{},JSON.parse('{"__proto__":{"aa":"hello"}}'))
Jquery可以用$.extend将两个字典merge,而这也因此污染了原型链。
Xnuca2019 Hardjs Wp
这道题预期解也就是非常和适宜的运用了上面两个原型链污染漏洞,首先lodash后台污染使得任意用户登录,然后JQuery前端污染进行XSS。做题目时觉得很有趣,但是一直没找到XSS的利用姿势就一直没做出来。
这道题目已经开源,大家可以自己搭建来玩https://github.com/NeSE-Team/OurChallenges/tree/master/XNUCA2019Qualifier/Web/hardjs
这题目给了源码,后台主要功能就是接收用户输入,插入数据库,然后可以打印出来。
但是当数据超过5条时,会调用lodash的defaultsDeep函数将其合并
for(var i=0;i<raws.length ;i++){
lodash.defaultsDeep(doms,JSON.parse( raws[i].dom ));
var sql = "delete from `html` where id = ?";
var result = await query(sql,raws[i].id);
}
后台污染任意登录
这样的话我们就可以利用上述lodash的污染原型链漏洞,污染什么属性好呢,我们发现验证登录auth函数仅通过req.session.login、req.session.userid判断登录,这样的话我们可以污染login和userid两个属性,就可以任意登录了。
function auth(req,res,next){
// var session = req.session;
if(!req.session.login || !req.session.userid ){
res.redirect(302,"/login");
} else{
next();
}
}
使用的express框架支持通过content-type接收输入,我们改为application/json
直接输入json数据。
因为在源码中我们看到了robot.py脚本,从中看到利用selenium登录网站,而密码就是flag。这样的话,前端如果能XSS就可以拿flag了。
前端Jquery 原型链漏洞XSS
在前端获取后台数据时调用了$.extent
函数merge数据
function getAll(allNode){
$.ajax({
url:"/get",
type:"get",
async:false,
success: function(datas){
for(var i=0 ;i<datas.length; i++){
$.extend(true,allNode,datas[i])
}
// console.log(allNode);
}
})
}
此时既然存在漏洞,就需要找到漏洞利用点。在使用js生成模板时,遍历了hints数组并将hints数组里面的内容写入到对应li标签中。
(function(){
var hints = {
header : "自定义内容",
notice: "自定义公告",
wiki : "自定义wiki",
button:"自定义内容",
message: "自定义留言内容"
};
for(key in hints){
// console.log(key);
element = $("li[type='"+key+"']");
if(element){
element.find("span.content").html(hints[key]);
}
}
})();
我们查看index.ejs中,含有type属性的li标签除了上面写的五个还有一个logger
<li type="logger">
<div class="col-sm-12 col-sm-centered">
<pre class="am-pre-scrollable">
<span class="am-text-success">[Tue Jan 11 17:32:52 9]</span> <span class="am-text-danger">[info]</span> <span class="content">StoreHtml init success .....</span>
</pre>
</div>
</li>
</ul>
这样我们可以尝试污染logger变量,使得hints含有logger属性,从而将logger内容打印到页面中实现XSS
因为不用登陆即可进入这个页面,那么robot就会向location跳转的我的页面提交账号密码,然后只要在服务器构造好一个表单,记录发送过来的post数据就行。
这道题有些师傅是污染ejs渲染模板某个变量getshell的,这种方法讨论的比较多且详细我这里就不赘述了。
Reference
https://snyk.io/blog/snyk-research-team-discovers-severe-prototype-pollution-security-vulnerabilities-affecting-all-versions-of-lodash/
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11358
https://www.cnblogs.com/bais/p/9068928.html
https://www.smi1e.top/javascript-%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93/
https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html