Definition
Inject Property
到一些 JavaScript 現有的物件(像是 Date 物件, 甚至是所有物件的根物件 Object)的 __proto__ 之中,或是直接 Modify
__proto__ 現有的 property
About __proto__ and prototype
How
直接去 add/modify 物件 __proto__ 的 property
1 | const a = {}; |
透過 JSON.parse() 搭配一些 property merging function 去更動 __proto__
1 | function merge(target, source) { |
為什麼不能
1
2
3
4
5
6
7const a = {};
const b = { __proto__: { hehe: 1 }};
merge(a, b);
const c = {}
console.log(c.b) // undefined- 透過宣告直接指定 __proto__ 會被視為真的是 b 的 __proto__, 也就是直接覆蓋掉了 b 的 __proto__, 而並非 b 身上的 property
- 但是透過 JSON.parse(), 會直接將 __proto__ 視為 b 身上的 property
透過 JSON.parse() 搭配一些 property merging function 去更動 constructor 中的 prototype
- 與上述更動 __proto__ 的方式雷同, 只是這次目標是 constructor.prototype
- constructor.prototype
- 物件皆有 constructor function, 即時是單純的 Object
- (constructor function 的 prototype) === (由該 constructor function 建構出來的 instance 的 __proto__)
Prototye pollution in lodash API (目前新版都已被修正)
_.merge()
1 | var payload = '{"__proto__": {"a": "hehe"}}'; |
_.defaultsDeep()
1 | const payload = '{"constructor": {"prototype": {"toString": true}}}' |
可能造成的 Security problems
Dos
- 情境
- 當 server 接收 client 送來的 payload, 進行 JSON.parse() 後 merge 到現有的資料中 (e.g. session data)
- 可以透過這個 payload 去修改 __proto__ , 竄改 Object 的一些 bulid-in function (e.g. toString()), 讓他拋出錯誤, 之後若在 server code 中有使用到 toString(), 就會造成 error, 進而 crash server
Property Injection
- 情境
- 透過 userA.isAdmin flag 來判斷 userA 是否具有 admin 權限
- 在 Object.prototype 中加入一個 isAdmin 並設為 true, 如此一來任何人(物件)在 prototype chain 上最終都會有 isAdmin 這個 property 且為 true
防範方法
在做 object merging/cloning 機制時, 需要擋掉 key === ‘__proto__’ 或是 key === ‘constructor’
Freeze the prototype — Object.freeze(Object.prototype)
- 使其不在能做任何 key 的增減修改