在使用JSON.parse之前,应该如何清除不受信任的JSON



给定一个用户提供的JSON字符串,我们如何在运行JSON.parse(untrustedString)之前对其进行清理?

我最关心的是原型污染,但我也想知道我还应该注意什么?如果只是原型污染是一种风险,那么我认为可以通过regex处理,但我怀疑还有其他问题吗?

例如,本文介绍了解析不受信任的JSON然后创建对象副本的危险

现在考虑一些发送到此端点的恶意JSON数据。

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

如果发送此JSON,JSON.parse将生成一个具有__proto__属性。如果复制库如上所述工作,它将把admin属性复制到的原型上req.session.user

我主要关心的是原型污染

请注意,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));

在使用它之前,userString只是一个字符串,该字符串中的任何内容本身都不会对系统造成伤害,除非系统采取了允许这种伤害的措施,比如以不安全的方式处理它。

输入JSON.parse()

JSON.parse()只是一个简单的格式转换工具。它不从数据中运行任何方法(原始污染利用依赖于这些数据(,甚至不从字符串化对象本身中包含的数据中查看,除了它包含的结构语法和JavaScript保留字之外,用于验证目的(MDN polyfill示例(。这里适用的原理与字符串相同;如果你没有对输出对象做任何不安全的事情,它不会伤害你或你的系统。

归根结底,防止滥用可以归结为验证安全数据处理实践

  • 检查解析字符串得到的对象,并验证它在严格的参数范围内,忽略原型突变。

  • 使用Object.prototype.hasOwnProperty.call()。强制执行这些使用esint等工具在代码库中进行实践(没有原型内置规则(。

  • 不要期望用户发送完美、安全的数据。

在你链接的文章中,作者提到了这个确切的想法:

。。。应该始终对来自用户的数据进行过滤和净化

可能最重要的是简单地限制大小。内存溢出可能超出应用程序沙箱的范围。

其次最重要的是关注自己的角色设置,并清理那些你不会处理的东西。

如果你不希望完全支持Unicode,那么明确地不支持它(在处理转义后,过滤到更简单的东西,如ASCII(,因为该代码很复杂,并且会碰到可能损坏的二进制层

最后,有一个明确的键列表,您支持并验证每个键中的值,这样您就不必担心应用程序逻辑会出错。

相关内容

  • 没有找到相关文章

最新更新