闭包代码的提权漏洞

在开发中,我们经常会碰到使用闭包的场景,我们使用闭包的目的,是想要对一些数据进行保护来避免外界修改,有这么一个闭包函数,我们来看看它存在的漏洞

javascript 复制代码
var o = (function(){
    var obj = {
        a: 1,
        b: 2
    };
    return {
        get(key) {
            return obj[key]
        }
    }
})()

o.get('a') // 1
o.get('c') // undefined

很简单的一个闭包,就是访问当前对象的属性值,那么思考一下,如何在不改变上述代码的情况下,我们如何获取到闭包对象obj的值呢?

valueOf

我们知道,对象的 valueOf 方法是返回其自身,我们来尝试看下

javascript 复制代码
o.get('valueOf')() // Cannot convert undefined or null to object

执行代码后,我们发现,程序报错了,为啥呢?

我们来看下 valueOf 的大概实现过程

javascript 复制代码
Object.prototype.valueOf = function() {
    // ...
    return this;
}

valueOf 的里的 this 取决于当前的调用对象,我们上述的代码可理解为这样

javascript 复制代码
var obj = {
    get() {
        return this
    }
}

var fn = obj.get;
fn(); // 指向了window

也就是说,o.get('valueOf') 只是拿到了其方法,执行时并没有指明 this

Object.defineProperty

我们来看下返回值 obj[key] ,通过这样的方式来返回对象的属性值,那么是否存在访问其属性值时返回其自身对象呢?例如访问某个属性时返回其自身。

我们知道 Object.defineProperty 的基本用法,需要给某个对象的某个属性做代理,那么前提是要知道需要代理的对象,这个好像又回到了开始的问题了,该给谁做代理呢?

访问对象的某个属性时,默认会先找自身,自身没有时会找其 原型链 上的属性。

由原型链作为突破口,我们可以给对象的原型链 Object.prototype 设置代理,代理其某个属性值(我们这里用 anyKey ),尝试去返回对象本身

javascript 复制代码
Object.defineProperty(Object.prototype, 'anyKey', {
    get() {
        return this
    }
})

o.get('anyKey') // {a: 1, b: 2} 拿到了闭包中的obj对象, o.get('anyKey')相当于obj['anyKey']

缺陷处理

通过 Object.defineProperty 可以访问到闭包里的obj对象,那么也就失去了闭包的意义了,那么如何处理这个缺陷呢?

断开原型链

我们在声明对象的时候,可以通过 Object.create(null)Object.setPrototypeOf 来生成一个原型对象为 null 的对象,那么就无法访问其原型链上的属性。修改如下

javascript 复制代码
var o = (function(){
    var obj = {
        a: 1,
        b: 2
    };
    // 修改1
    Object.setPrototypeOf(obj, null)
    return {
        get(key) {
            return obj[key]
        }
    }
})()

var o = (function(){
    // 修改2
    var obj = Object.create(null);
    obj.a = 1;
    obj.b = 2;
    return {
        get(key) {
            return obj[key]
        }
    }
})()

hasOwnProperty

如果不想断开原型链,那么我们可以校验其属性是否是对象自身所拥有的属性,来规避这个漏洞。我们则可以做这样的更改。

javascript 复制代码
var o = (function(){
    var obj = {
        a: 1,
        b: 2
    };
    return {
        get(key) {
            // 修改
            if (obj.hasOwnProperty(key)) return obj[key]
        }
    }
})()
相关推荐
ningmengjing_3 分钟前
在 PyCharm 中安装并配置 Node.js 的指南
开发语言·javascript·ecmascript
晓131318 分钟前
JavaScript基础篇——第五章 对象(最终篇)
开发语言·前端·javascript
灋✘逞_兇1 小时前
Node.Js是什么?
服务器·javascript·node.js
小飞悟2 小时前
那些年我们忽略的高频事件,正在拖垮你的页面
javascript·设计模式·面试
中微子2 小时前
闭包面试宝典:高频考点与实战解析
前端·javascript
G等你下课2 小时前
告别刷新就丢数据!localStorage 全面指南
前端·javascript
爱编程的喵3 小时前
JavaScript闭包实战:从类封装到防抖函数的深度解析
前端·javascript
前端Hardy3 小时前
8个你必须掌握的「Vue」实用技巧
前端·javascript·vue.js
星月日3 小时前
深拷贝还在用lodash吗?来试试原装的structuredClone()吧!
前端·javascript
爱学习的茄子3 小时前
JavaScript闭包实战:解析节流函数的精妙实现 🚀
前端·javascript·面试