闭包代码的提权漏洞

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

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]
        }
    }
})()
相关推荐
星栈独行1 小时前
翻完 Pi 源码:它和 Codex、Claude Code 有何不同
开发语言·javascript·人工智能·程序人生
落落Plus2 小时前
浏览器缓存机制详解
javascript·缓存·浏览器缓存
浅水壁虎4 小时前
vue基础(第二章 )
前端·javascript·vue.js
界面开发小八哥4 小时前
界面控件DevExtreme v26.1新版亮点——支持Angular 22
前端·javascript·angular.js·devexpress·ui开发·devextreme
mONESY5 小时前
React useState 核心原理与最佳实践:从异步更新到性能优化全解
javascript
腻害兔6 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
gis开发之家7 小时前
《Vue3 从入门到大神37篇》Vue3 源码详解(七):watch 与 watchEffect 源码对比——副作用是如何被追踪的?
javascript·前端框架·vue3·vue3源码
bloglin999998 小时前
langchain 和 langgraph 和 react
javascript·react.js·langchain
触底反弹8 小时前
🚀 删了数据刷新又回来?3 组件 × 4 回调 × 3 坑讲透 React 父子通信
前端·javascript·react.js
会周易的程序员10 小时前
js-shm: 高性能 Node.js 共享内存模块
开发语言·javascript·c++·node.js·共享内存·shm