闭包提权漏洞:修改私有对象的属性

问题来源

以前在面试过程中发现一道有趣的题,抖音刷到了袁进老师的视频,对该问题有了更进一步的认识,记录一下。

面试题内容

如何在不改变源代码的情况下,修改 o 对象的属性?

1
2
3
4
5
6
7
8
9
10
11
let o =(function () {
var obj = {
a: 1,
b: 2,
};
return {
get: function (key) {
return obj[key];
},
};
})()
  1. 首先要读一个对象,就会想到读对象的原型,原型有 valueOf 方法,可以读到对象
1
console.log(o.get("valueOf")); // output : [Function: valueOf]
  1. 读到 valueOf 方法,可以调用 valueOf 方法,读到对象
1
2
3
4
console.log(o.get("valueOf")()); // output : error - 知识点1:this指向问题
// 上述代码等同于
let handleValueOf = o.valueOf;
handleValueOf(); // output : error this不指向对象本身
  1. valueOf 无法读到对象本身,可以直接使用 Object.defineProperty 增加一个返回对象本身的方法
1
2
3
4
5
Object.defineProperty(Object.prototype, "hack", {
get: function () {
return this;
},
});
  1. 同多原型链自定义方法访问到私有对象本身,更改 o 对象本身,就实现了上述功能
1
2
3
4
5
let objectBackup = o.get("hack");

objectBackup.c = "hackInner";

console.log(o.get("c")); // 'hackInner'

防御

  1. 原型设置为 null
1
2
3
4
5
6
7
8
9
10
11
12
13
let o =(function () {
var obj = {
a: 1,
b: 2,
};

Object.setPrototypeOf(obj, null);
return {
get: function (key) {
return obj[key];
},
};
})()
  1. 在访问器中判断是否自身携带属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let o = (function () {
var obj = {
a: 1,
b: 2,
};

return {
get: function (key) {
if (obj.hasOwnProperty(key)) {
return obj[key];
}
},
};
})()

总结

一切代码皆有漏洞,需要谨慎编写,尽量防御


闭包提权漏洞:修改私有对象的属性
https://blog.funfe.cn/2024/03/13/20240313123053/
作者
李鹏杰
发布于
2024年3月13日
许可协议