javascript 在使用JSON.parse之前应该如何清理不受信任的JSON?

mbyulnm0  于 2023-05-12  发布在  Java
关注(0)|答案(3)|浏览(263)

给定一个用户提供的JSON字符串,我们如何在运行JSON.parse(untrustedString)之前清理它?
我主要担心的是原型污染,但我也想知道我还应该注意什么?如果只是原型污染是一个风险,那么我假设可以通过正则表达式处理,但我怀疑还有其他问题?
例如,this article on the dangers of parsing untrusted JSON and then creating a copy of the object.
现在考虑发送到该端点的一些恶意JSON数据。

{
  "user": {
    "__proto__": {
      "admin": true
    }
  }
}

如果这个JSON被发送,JSON.parse将生成一个带有__proto__属性的对象。如果复制库按上述方式工作,它将把admin属性复制到req.session.user的原型上!

5lhxktic

5lhxktic1#

我主要关心的是原型污染
请注意,JSON.parse不会污染任何原型对象。如果JSON字符串有一个"__proto__"键,那么该键将像任何其他键一样被创建,无论对应的值在JSON中是什么,它最终都会作为该属性值,而不是在原型对象(Object.prototype)中。
风险在于你在 * 之后 * 对那个对象做了什么。如果你使用属性赋值或Object.assign执行(深度)复制,* 那么 * 你可能会改变原型对象。
我们如何在运行JSON.parse(untrustedString)之前清理它?...我假设可以通过regex处理
不要使用正则表达式。使用JSON.parse的第二个参数:

const cleaner = (key, value) => key === "__proto__" ? undefined : value;

// demo
let json = '{"user":{"__proto__":{"admin": true}}}';

console.log(JSON.parse(json));
console.log(JSON.parse(json, cleaner));
nfzehxib

nfzehxib2#

在你对它做任何事情之前,userString只是一个字符串,这个字符串本身没有任何东西可以伤害系统,除非系统做了一些允许这种伤害的事情,比如以不安全的方式处理它。
输入JSON.parse()
JSON.parse()是一个简单的格式转换工具。它不运行数据中的任何方法(proto pollution profits依赖),甚至不需要“查看”字符串化对象本身包含的数据,除了structural syntax it contains和JavaScript保留字,以用于验证目的(MDN polyfill示例)。这里的原理和弦一样适用;如果你不对输出对象做任何不安全的事情,它就不会伤害你或你的系统。
最终,防止滥用可以简单地归结为验证安全数据处理实践

article you linked中,作者提到了这个确切的想法:

...来自用户的数据应始终进行过滤和清理。

mdfafbf1

mdfafbf13#

也许最重要的是简单地限制大小。内存溢出可能会超出应用程序沙箱的范围。
下一个最重要的事情是关注你自己的角色集,并清理你不打算工作的东西。
如果您不期望完全支持Unicode,那么明确地不支持它(在处理转义之后,过滤到更简单的代码,如ASCII),因为代码很复杂,会碰到可能被破坏的二进制层
最后,有一个明确的键列表,您支持并验证每个键中的值,这样您就不必担心应用程序逻辑出错。

相关问题