"Object.fromEntries()"是否安全,不会受到原型污染



考虑以下JavaScript中原型污染的简单示例:

function sayHello(name) {
console.log(`Hi ${name}!`);
}
// Pollute the prototype
({}).__proto__.toString = () => alert('hacked');
// Trigger the exploit
sayHello({});

我想知道Object.fromEntries是否可以进行类似的攻击,所以我测试了:

function sayHello(name) {
console.log(`Hi ${name}!`);
}
// Try to pollute the prototype, but doesn't work, even for the same object!
const x = Object.fromEntries([['__proto__', { toString: () => alert('hacked') }]]);
// Try to trigger the exploit, but fail
sayHello({}); // Hi [object Object]
sayHello(x); // Hi [object Object]

事实上,内置的Object.fromEntries是安全的,不会受到这种攻击,这很好,我期待得到一些保护。然而,我以为它会抛出错误或跳过设置__proto__,但令我惊讶的是,__proto__实际上已经设置好了!

x.__proto__.toString(); // Exploited!
x.toString(); // Not exploited!!

我很惊讶Object.fromEntries成功创建了一个对象,其.__proto__.toString被利用,而.toString没有。

那么,这安全吗?

对于未检查的用户提供的数据,我可以安全地使用Object.fromEntries

我可以安全地将Object.fromEntries与未检查的用户提供的数据一起使用吗?

是的,它永远不会通过构建对象来修改Object.prototype

我很惊讶Object.fromEntries成功创建了一个对象,其.__proto__.toString被利用,而.toString没有。

这里.__proto__没有什么特别之处,它只是Object.prototype上的getter/setter属性,类似于hasOwnPropertyisPrototypeOf

您会注意到Object.fromEntries确实构建了一个具有自己的.__proto__属性的对象,以及x.__proto__ !== Object.prototype(尽管仍然是Object.getPrototypeOf(x) === Object.prototype(。继承的属性被隐藏。

相关内容

  • 没有找到相关文章

最新更新