/sep 19, 2022

Analysis and Remediation Guidance of CSRF Vulnerability in Csurf Express.js Middleware

By Mateusz Krzeszowiec

Technical Summary

On 28th of August fortbridge.co.uk reported a vulnerability in csurf middleware – expressjs supporting library that enables CSRF protection in expressjs.

As of 13th of September csurf library has been deprecated with no plans to fix the vulnerabilities.

There is no viable alternative for csurf middleware now.

Am I Affected?

All versions of csurf library are vulnerable if:

  • csurf is setup to use double-submit cookies – csurf({cookie: true})
  • and default value function is in use
     

Setting up cookie signatures as described here: https://www.npmjs.com/package/csurf#cookie does not prevent the bypass

Indicators of an Attack

Reliable indicator of attempted exploitation would include either:

  • request query variable _csrf with a value
  • request body variable _csrf with a value
     

This is assuming the default value function is in use as described here: https://www.npmjs.com/package/csurf#value

If verbose access logs are enabled there’s another indicator that may be useful.  In case of an attack the secret will be passed from the client to the server via _csrf cookie without corresponding set Cookie header in one of the previous server responses for a given secret value.

Remediation

  1. A short-term fix would require csurf library to run in a session-backed (or synchronizer pattern) mode by setting: csurf({cookie: false}). The application may require a rearchitecture and modifications beyond simple csurf configuration change.
  2. If it’s not feasible to use session-backed csurf it may still be possible to setup csurf with a custom value function as described here: https://owasp.org/www-pdf-archive/David_Johansson-Double_Defeat_of_Double-Submit_Cookie.pdf, that is together with a review of CORS setup for a given application. Special care must be taken when reviewing CORS settings when https://www.npmjs.com/package/cors middleware is in use. Additionally, cookies that contain the secret should be renamed to contain __Host- prefix so it cannot be tossed from a subdomain.
     

Option #1 doesn’t have any known weaknesses but may be far more costly to implement than #2.

Option #2 leaves the target application prone to attacks in case of misconfigured CORS policy, especially if Access-Control-Allow-Credentials is in use.

Given that Express.js maintainers are unable to resolve the outstanding issues due to lack of resources it may be necessary to either develop CSRF protection middleware in-house or shift away from Express.js entirely.

How Veracode Helps You Address CSRF Vulnerability

Thanks to our Software Composition Analysis (SCA) product, you can quickly verify whether the application portfolio you’re scanning with us is affected and at elevated risk exploitation.

To verify whether your applications are using vulnerable csurf library, log in to the Veracode Platform. Check if you’re using csurf by following these guides: https://docs.veracode.com/r/c_SCA_comps

*Please note* Veracode SCA customers can scan for this vulnerability across their applications. The entry for the vulnerability in our database is here: https://sca.analysiscenter.veracode.com/vulnerability-database/libraries/csurf/javascript/npm/lid-3174/summary

Detailed Analysis

Recently, Fortbridge, a small application security company announced several vulnerabilities in expressjs security library or middleware – csurf. This has been quickly picked up by one of the mainstream security news outlets – The Daily Swig.

The report by Fortbridge seems to be a re-discovery of a vulnerability in csurf originally discussed in 2017 by Davin Johansson in his “Bypassing CSRF Protections” talk during OWASP London chapter lightning talk.

Fortbridge stated that csurf library, in its default configuration, is prone to cross site request forgery protection bypass thanks to cookie tossing and logic error in request processing.

An adversary in control of a subdomain of a benign website, either due to subdomain takeover, cross-site scripting vulnerability in the beforementioned subdomain, or insecure architecture of an application, will be able to bypass cross site request forgery protection in csurf library. Subdomain takeover is one of the most common security problems found in bug bounty programs, so it won’t be a significant obstacle for a motivated attacker.

Although Fortbridge described that the secret used to generate CSRF token is the main culprit I believe that this is only partially true. Certainly, it indicates a lack of understanding of double-submit cookie pattern in general, but this wouldn’t make any difference in case of cookie tossing. Whether adversary will toss the secret or actual token would be irrelevant – bypass would still occur.

The crucial element of the exploit is that the adversary doesn’t even have to attempt to bypass CORS restrictions as request query or request body parameters are not subject to CORS.

Now we could normally assume that modern browsers will handle CORS correctly and prevent csurf bypass in case broken, default, value function (see: https://github.com/expressjs/csurf/blob/741f484131cd257fdb1052a047c4579c862687ea/index.js#L130) is replaced by reasonable implementation that’ll accept CSRF token from headers only.

This is largely true but unfortunately another, broken, middleware comes into the picture.

While investigating csurf issues I realized that there’s another avenue available to bypass csrf protection when double-submit cookie pattern is in use. It would require CORS configuration that include:

  1. Access-Control-Allow-Credentials response header set to true
  2. Access-Control-Allow-Origin set to subdomain taken over by the attacker
  3. Access-Control-Allow-Headers configured
     

Headers mentioned in points #a and #b would be commonly setup if an application is using cookie-based session. If Access-Control-Allow-Origin permits communication from subdomain, then the header Access-Control-Allow-Headers becomes single point of failure for the CSRF attack prevention.

Very popular https://www.npmjs.com/package/cors package, will, by default, reflect Access-Control-Request-Headers as described here: https://www.npmjs.com/package/cors#configuration-options.

This insecure default in CORS library further weakens double-submit cookie pattern protection.

As a sidenote, csurf middleware is using csrf npm package for secret and token generation. csrf package doesn’t use cryptographically secure random number generator to protect the secret. Instead, it utilizes rndm package which is equivalent to Javascript Math.random() call which is easily guessable. While this doesn’t significantly increase the risk of exploitation it demonstrates a lack of security review of the csurf and related libraries.

With a steady stream of weaknesses discovered in this area it may be necessary to revisit the threat model for the double-submit cookie pattern and see if it is still acceptable for your business requirements. Double-submit cookie pattern may be sufficient protection against CSRF attacks but must be implemented correctly and with additional security controls like cookie prefixes and very careful CORS configuration.

References

Related Posts

By Mateusz Krzeszowiec

Mateusz Krzeszowiec is a Principal Security Researcher at Veracode. He started his career as software engineer and after good couple of years transitioned into application security. Mateusz worked as builder, breaker, and defender in a handful of enterprises. He researches various languages and technologies and contributes to Veracode's Binary Static Analysis service.