/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 attampted 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 thesecret will be passed from the client to the server via _csrf cookie without corresponding setCookie header in one of the previous server responses for a given secret value.

Remediation

  1. A short term fix would require csurf library to be runing in a session-backed (or synchronizer pattern) mode by setting: csurf({cookie: false}). This may require rearchitecting the application and requires changes 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, cookie 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 the 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 inhouse or move away from Express.js entirely.

How Veracode Helps You Address this Problem

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

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 are able to 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 outlet – The Daily Swig.

The report by Fortbridge seem 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 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’s an indicator of lack of understanding 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.

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 will permit 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 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 threat model for the double submit cookie pattern and see if it still acceptable for your business requirements. Double submit cookie pattern may be sufficient protection against CSRF attacks but must be implemented correctly and with an 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.