← 返回首页
闭包代码的提权漏洞
发表时间:2023-09-17 03:43:45
闭包代码的提权漏洞

我们知道闭包最大的意义在于:使得函数的局部变量在函数执行完毕后,仍然驻留内存。很多第三方库和一些公共组件利用闭包这一特性,可以屏蔽函数的内部对象不被外部随意修改。

我们看下面实例:

let o = (function(){
    let obj = {
        name: 'zhangsan',
        age : 18
    }
    return{
        get:function(k){
            return obj[k];
        }
    }
})();


console.log(o.get('name'))
console.log(o.get('age'))

//obj对象无法直接访问。
/*
obj.name = 'lisi';
console.log(o.get('name'))
console.log(o.get('age'))
*/

运行结果:

zhangsan
18

但是,这里我们忽略了闭包代码存在的提权漏洞现象。我们可以利用Object.defineProperty获取闭包对象。

程序改写如下:

let o = (function(){
    let obj = {
        name: 'zhangsan',
        age : 18
    }
    //Object.setPrototypeOf(obj,null);
    return{
        get:function(k){
            return obj[k];
        }
    }
})();


console.log(o.get('name'))
console.log(o.get('age'))


Object.defineProperty(Object.prototype,'primaryObject',{
    get(){
        return this;
    }
});

console.log(o.get('primaryObject'))

let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;

console.log(o.get('name'))
console.log(o.get('age'))

运行结果:

zhangsan
18
{ name: 'zhangsan', age: 18 }
lisi
20

解决这个漏洞有以下两种方案:

1).断开原型链。

let o = (function(){
    let obj = {
        name: 'zhangsan',
        age : 18
    }
    //断开原型链
    Object.setPrototypeOf(obj,null);
    return{
        get:function(k){
            return obj[k];
        }
    }
})();


console.log(o.get('name'))
console.log(o.get('age'))


Object.defineProperty(Object.prototype,'primaryObject',{
    get(){
        return this;
    }
});

console.log(o.get('primaryObject'))

let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;

console.log(o.get('name'))
console.log(o.get('age'))

2).使用hasOwnProperty判断是否是对象的真正属性。

let o = (function(){
    let obj = {
        name: 'zhangsan',
        age : 18
    }
    //Object.setPrototypeOf(obj,null);
    return{
        get:function(k){
            if(obj.hasOwnProperty(k)) {
                return obj[k];
            }
        }
    }
})();


console.log(o.get('name'))
console.log(o.get('age'))


Object.defineProperty(Object.prototype,'primaryObject',{
    get(){
        return this;
    }
});

console.log(o.get('primaryObject'))

let primaryObj =o.get('primaryObject')
primaryObj.name = 'lisi';
primaryObj.age = 20;

console.log(o.get('name'))
console.log(o.get('age'))