Dynamically insert encrypted token pattern CSRF token using __cfduid as a nonce

recipe-exchange

#1

I wanted to use Cloudflare’s Cache Everything feature on our website, but I was unable to because of the CSRF protection that our e-commerce store implemented. Requests needed to reach the origin server so that a unique CSRF token could be generated for the user, which is then required for future POST requests.

I solved this problem by creating a Cloudflare Worker script that generates a CSRF token utilizing the encrypted token pattern. The script uses the __cfduid cookie as a nonce. This variable is generated by Cloudflare and is unique to each client. Using this script the origin server is able to verify that the cookie containing the CSRF token was generated by the Cloudflare Worker script. It does this by using the shared secret and the __cfduid nonce. Be sure to modify the “shared_secret” variable on line 26 to a custom value unique to your application.

An example PHP function used in conjunction with the Cloudflare Worker script in Magento 1.x to determine if a client’s CSRF token is valid.


#2

Hey Scott,

Just wanted to let you know that this approach provides no protection against CSRF at all.

It sets a cookie on the client with a secret value, calculated from the __cfduid. But this cookie is sent on every crossdomain request as well - just like the normal session cookie - so no CSRF protection here.

Also refer to:

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

Section “Prevention measures that do NOT work”.

If I’m wrong about anything, I’m happy to be corrected.


#3

I think you are right. Thank you for pointing that out. I wanted to use a cookie to avoid having to completely rewrite the cached page, searching and replacing for some identifier in the text (IE “-+CSRF_TOKEN-+”). That’s the only other option I can think of for being able to implement CSRF protection using cached Cloudflare pages.

Let me know your thoughts. Thanks!


#4

No problem, I’m also looking for a solution without changing the origin application.

I think checking the origin / referer header for non-idempotent requests might work just as well, at least that’s what OWASP recommends as well as a first protection mechanism:

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Verifying_Same_Origin_with_Standard_Headers

I created the following worker script:

Please have a look and tell me if you see any issues. Thanks!