在js中和Python一样,万物皆对象。以此为基础可能好理解一点。

首先要理解prototype和_proto_。(我理解不了)

787416-20160323103557261-114570044.png


prototype是函数才有的,__proto__是每个对象都有的。
这里new了一个b之后发现prototype是空。

1.PNG


而每一个proto都会指向上一级的prototype:

> b.__proto__===a.prototype
true

原型链就是由proto一级一级构成的:
(我不知道能不能理解为a的proto就是a的原型对象,a.proto.proto就是object的原型对象,a.pro.pro.pro就是null。)

2.PNG

引用一句总结:

每个构造函数(constructor)都有一个原型对象(prototype)
对象的__proto__属性,指向类的原型对象prototype
JavaScript使用prototype链实现继承机制

那么原型链污染就是通过能修改函数的proto属性去更改上级类:

3.PNG


这里通过修改test1的proto去更改了test类中的name。
导致再实例化出test2的时候他的name值就成了1111111.

最后就是网鼎杯的notes了。
[网鼎杯 2020 青龙组]notes:
有源码,可以执行命令:

4.PNG


只能执行commands里面的。但是这里这个列表是不可控的。
所以只能去搞他的上级。就像这样:

5.PNG


这里commands本来只有两个元素,但是使用payload的proto污染字典后,commands中多出了c。
所以想办法找到一个可以操作字典的地方就行了。

6.PNG


这里跟进add_note路由找到write_note,发现键名是不可控的。
但是他下面的edit_note键名是可控的。
undefsafe(this.note_list, id + ‘.author’, author);
这里如果id=__proto__那么就相当于上面的payload.proto.author=author
所以只要id传入__proto__,author传入命令即可。
但是:

7.PNG


edit_note路由中有个判断要求raw也要有数据。 呢么post的时候可以发发牢骚。

8.PNG


然后去status执行应该就能打过来了:
9.PNG

study:
https://snyk.io/vuln/SNYK-JS-UNDEFSAFE-548940
https://imagin.vip/?p=1391# notes
https://github.com/remy/undefsafe/commit/f272681b3a50e2c4cbb6a8533795e1453382c822