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工具库

运行上面的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函数将其合并

后台污染任意登录

这样的话我们就可以利用上述lodash的污染原型链漏洞,污染什么属性好呢,我们发现验证登录auth函数仅通过req.session.login、req.session.userid判断登录,这样的话我们可以污染login和userid两个属性,就可以任意登录了。

使用的express框架支持通过content-type判断接收输入,我们改为application/json直接输入json数据。

因为在源码中我们看到了robot.py脚本,从中看到利用selenium登录网站,而密码就是flag。这样的话,前端如果能XSS就可以拿flag了。

前端Jquery 原型链漏洞XSS

在前端获取后台数据时调用了$.extent函数merge数据

此时既然存在漏洞,就需要找到漏洞利用点。在使用js生成模板时,遍历了hints数组并将hints数组里面的内容写入到对应li标签中。

我们查看index.ejs中,含有type属性的li标签除了上面写的五个还有一个logger

这样我们可以尝试污染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

发表评论

电子邮件地址不会被公开。 必填项已用*标注