简体   繁体   English

express.js 我们应该对 req.body 有多怀疑?

[英]express.js How suspicious should we be of req.body?

https://expressjs.com/en/4x/api.html states https://expressjs.com/en/4x/api.html状态

As req.body's shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting.由于 req.body 的形状基于用户控制的输入,因此此 object 中的所有属性和值都是不受信任的,应该在信任之前进行验证。 For example, req.body.foo.toString() may fail in multiple ways, for example foo may not be there or may not be a string, and toString may not be a function and instead a string or other user-input.例如, req.body.foo.toString() 可能以多种方式失败,例如 foo 可能不存在或可能不是字符串,并且 toString 可能不是 function 而是字符串或其他用户输入。

I think I understand this (to a limited degree) in the context of prototype pollution reading https://github.com/expressjs/body-parser/issues/347 and https://learn.snyk.io/lessons/prototype-pollution/javascript/ (don't perform certain operations on unvalidated objects that may pollute proto or constructor)我在阅读https://github.com/expressjs/body-parser/issues/347https://learn.snyk.io/lessons/prototype-的原型污染的背景下理解这一点(在有限程度上) 污染/javascript/ (不要对可能污染原型或构造函数的未验证对象执行某些操作)

I take it that without such an operation being performed (the merge function in the Snyk example) req.body.foo.toString() cannot itself immediately contain remote / user supplied code?我认为如果不执行这样的操作(Snyk 示例中的合并 function) req.body.foo.toString() 本身不能立即包含远程/用户提供的代码吗? (that is for the toString() function to be completely arbitrary?). (也就是说 toString() function 是完全任意的?)。

Or have I misunderstood, and it would be necessary to Check if a variable is a string in JavaScript on req.body.foo before being safe to call its toString()?还是我误解了,在安全地调用它的 toString() 之前,有必要检查变量是否是 req.body.foo 上 JavaScript 中的字符串

Many thanks非常感谢

Express will not allow custom code to sneak into req.body . Express 不允许自定义代码潜入req.body So, you don't have to worry about malicious code in .toString() method being on a particular property, but it is possible that an object in req.body could have a custom property called .toString that has a value (something other than code) as was illustrated in your learn.snky.io example.因此,您不必担心.toString()方法中的恶意代码位于特定属性上,但是 req.body 中的req.body可能具有名为.toString的自定义属性,该属性具有值(其他比代码)如您的learn.snky.io示例中所示。

Keep in mind that req.body in Express comes from parsing the body of the incoming request.请记住,Express 中的req.body来自解析传入请求的正文。 That body will have been encoded according to the content-type.该正文将根据内容类型进行编码。 Most commonly, it will be applications/json or application/x-www-form-urlencoded and neither of these encodings has any way for the sender to include Javascript code that will become live code as part of the decoding.最常见的是,它是applications/jsonapplication/x-www-form-urlencoded并且这些编码都不能让发送者包含 Javascript 代码,该代码将成为实时代码作为解码的一部分。 So, those content-types are safe from live code injection.因此,这些内容类型不受实时代码注入的影响。 Now, there could be code in a property as a string, but it won't be live or executed unless you do something incorrect in how you use that data (like call eval() on it).现在,属性中可能有作为字符串的代码,但除非您在使用该数据的方式上做了一些不正确的事情(例如在其上调用eval() ,否则它不会生效或执行。

And, you do NOT necessarily know what type a given property is on req.body .而且,您不一定知道req.body上的给定属性是什么类型。 You may be expecting the client to send a string for a property value, but it may be sending a number or an object (which both have different .toString() implementations).您可能希望客户端发送一个字符串作为属性值,但它可能发送一个数字或 object(两者都有不同的.toString()实现)。

If you're expecting the value to be a string, you can verify that it is a string by checking if (typeof req.body.foo === "string") and, if it is a string, you don't need to call .toString() on it as it's already a string.如果您希望该值是一个字符串,您可以通过检查if (typeof req.body.foo === "string")来验证它是否是一个字符串,如果它是一个字符串,则不需要调用.toString() ,因为它已经是一个字符串。

Robust protection for your server will verify the type of each incoming property you intend to use in req.body before attempting to use it and it will be very careful in how it copies information from req.body to other objects because you can create prototype pollution if you use the wrong method for copying.对服务器的强大保护将在尝试使用之前验证您打算在req.body中使用的每个传入属性的类型,并且在将信息从req.body复制到其他对象时会非常小心,因为您可以创建原型污染如果您使用错误的复制方法。 And, to avoid any funky method replacements that might be on an object in req.body , you can copy the single property to a fresh object and use it there.而且,为了避免可能在 req.body 中的req.body上出现任何时髦的方法替换,您可以将单个属性复制到新的 object 并在那里使用它。

My safe and simple rule is to first check the type and validate the value of any property I want to use and then copy individual named properties only from req.body to my own objects.我的安全且简单的规则是首先检查类型并验证我想要使用的任何属性的值,然后仅将单个命名属性从req.body到我自己的对象中。 I never copy entire objects using functions that recursively copy all properties.我从不使用递归复制所有属性的函数复制整个对象。 That's how you become vulnerable to prototype pollution, by blindly copying things from req.body that aren't the known properties you're expecting.这就是你如何通过盲目地从req.body复制不是你期望的已知属性的东西而变得容易受到原型污染的影响。

If I want to copy 10 properties to another object, I will make an array of the 10 property names and use a loop to copy those 10 named properties individually, leaving behind any other potentially malicious properties (such as __proto__ that I don't want).如果我想将 10 个属性复制到另一个 object,我将创建一个包含 10 个属性名称的数组并使用循环单独复制这 10 个命名属性,留下任何其他潜在的恶意属性(例如__proto__我不想要)。 If I'm just using a couple properties, I will just manually assign them to a new object that I created.如果我只使用几个属性,我将手动将它们分配给我创建的新 object。 I will not use things like Object.assign() to bulk copy from req.body because that can and will copy things that I do not want polluting my own programming objects.我不会使用Object.assign()类的东西从req.body批量复制,因为它可以并且会复制我不想污染我自己的编程对象的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM