Cross-Site Request Forgery, or CSRF, is a type of attack that developers are familiar with in traditional web applications, but often misunderstand or forget about when it comes to new REST API’s. Fortunately, much of this misunderstanding and lack of consideration occurs because full page applications often don’t need to worry about CSRF. While many architectural differences in REST reduce the risk of CSRF attacks, that doesn’t mean we can simply ignore them entirely. Express’s body-parser module is a great recent example of this.
When you don’t need CSRF protection
When you do need CSRF protection
So how does all of this relate to express’s body-parser module? If you’re using Nodejs and express, there is a very high chance that your building a server side API. The de facto way to parse JSON in express is body-parser, and the code they always recommend using is:
The problem with the above code is that if you use it, you need CSRF protection. In your route middleware, body-parser will map JSON data to the
req.body object present in each request. However, when you call both
bodyParser.urlencoded() you are populating
req.body with content from both JSON sources and form-encoded sources. Your API route handlers cannot tell the difference between what Content-Type populated the API.
Making it safe
If your app has this, there are multiple ways you can fix this:
- Use traditional CSRF tokens for all requests
- Remove the
bodyParser.urlencodedmiddleware from API routes
- Check the
Content-Typeheader of the request
Personally, I’d recommend removing the
bodyParser.urlencoded middleware, since it’s the most straightforward in my opinion. If you parse any sort of traditional HTML form, such as for user login, then you will need to be add the
bodyParser.urlencoded middleware support on that route, but keep it off all the others! The documentation covers how to do this.
Beware example code
In summary, this isn’t an actual vulnerability or something that is wrong with body-parser. The author provided defaults that would cover the use case for 99% of the middleware’s users. This is a configuration-based insecurity, and is great example of how even simple example code can lead to a vulnerability in your own application. Don’t trust code blindly, be sure to understand what you’re putting in your application and how it affects your security.
This is a side effect of my recent messing around with CSRF. If you’d like to see more articles like this, follow me on Twitter.