JavaScript原型链污染:从“西门庆“到“武大郎“的奇妙转变 代码解析

JavaScript原型链污染:从"西门庆"到"武大郎"的奇妙转变 代码解析

代码解析

让我们先来看这段有趣的JavaScript代码:

let o = (function () {
  let obj = {
    name: '西门庆',
    age: 18
  }
  return {
    get(key) {
      return obj[key]
    },
  }
})();

const { get } = o;

// 通过修改原型链来影响 obj
Object.defineProperty(Object.prototype, 'proObj', {
  get() {
    return this;
  }
});

let obj = o.get('proObj')

obj.name = '武大郎'

console.log(get('name'));  // 现在输出 '武大郎' 而不是 '西门庆'

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

代码执行流程分析

1.创建闭包对象:

  • 使用立即执行函数(IIFE)创建一个闭包,内部包含一个私有对象obj,初始值为{name: ‘西门庆’, age: 18}

  • 返回一个包含get方法的对象,该方法可以访问私有obj

2.解构赋值:

  • 从对象o中解构出get方法

3.原型链污染:

  • 关键步骤:通过Object.defineProperty在Object.prototype上定义了一个名为proObj的访问器属性

  • 这个属性的getter返回this,即访问该属性时的对象本身

4.利用原型链获取私有对象:

  • 调用o.get(‘proObj’)时,首先在私有obj上查找proObj属性

  • 当私有obj上没有这个属性时,会沿着原型链向上查找

  • 在Object.prototype上找到了proObj属性,触发getter,返回了私有obj本身

5.修改私有对象:

  • 现在可以通过返回的引用直接修改闭包内的私有对象

  • 将name属性从"西门庆"改为"武大郎"

6.验证修改:

  • 再次通过get方法获取name属性,发现已变为"武大郎"

  • 通过o.get(‘proObj’)可以直接获取到私有obj的引用

技术原理
这段代码展示了JavaScript中几个重要的概念:

1.原型链(Prototype Chain):

  • JavaScript对象有一个隐藏的[[Prototype]]属性,指向它的原型对象

  • 当访问对象属性时,如果对象自身没有该属性,会沿着原型链向上查找

2.闭包(Closure):

  • IIFE创建了一个闭包,使得内部变量obj对外不可见

  • 正常情况下,外部代码无法直接访问或修改这个私有变量

3.原型污染(Prototype Pollution):

  • 通过修改Object.prototype,我们实际上污染了所有对象

  • 这是一种潜在的安全风险,可能被恶意利用

4.访问器属性(Accessor Property):

  • 使用Object.defineProperty定义的proObj是一个访问器属性

  • 它的getter函数返回this,即访问该属性的对象本身

实际应用中的防护

为了防止这类原型链污染攻击,可以采取以下措施:

1.使用Object.hasOwnProperty检查属性:

get(key) {
  if (obj.hasOwnProperty(key)) {
    return obj[key];
  }
  return undefined;
}

2.创建无原型的对象:

let obj = Object.create(null);
obj.name = '西门庆';
obj.age = 18;

3.冻结或密封对象:

Object.freeze(obj); // 或 Object.seal(obj);

这段代码巧妙地利用了JavaScript的原型链机制,突破了闭包的封装,实现了对私有变量的访问和修改。它不仅展示了JavaScript语言的灵活性,也提醒开发者注意潜在的安全风险。在实际开发中,我们应该谨慎处理对象属性访问,特别是当属性名来自不可信来源时。

通过这个"西门庆"变"武大郎"的例子,我们可以更深入地理解JavaScript的原型链和闭包机制,以及它们可能带来的安全问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星月前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值