Intelligence in Hacker's Perspective: Tips for Defenders

Hacker's Perspective: A Modern Approach to Cross-Site Request Forgery

When I first began my journey into Application Security, I found it difficult to wrap my head around CSRF, Cross-Origin Resource Sharing, and cookie-based authentication. I set out to find the differences between client-side code, server-side code, browsers, and how the three interact with each other.

Below I’ll explain how they can all be used to locate and exploit Cross-Site Request Forgery within modern web applications.

To discover Cross-Site Request Forgery (CSRF) within a modern web application, you need to make sure the app is using cookies to authenticate users. This is because JWT’s (JSON Web Tokens) are not vulnerable to CSRF since they are not automatically added to cross-site requests like cookies are.

So, to make CSRF work you must find one of the following three occurrences:

Find an application that does a state-change within a GET request

Common state-changes I look for when testing are password resets, account invites, or user role changes. Even if the parameters are passed within POST data, it’s worth trying them as GET parameters and seeing if the app accepts them. If it does, you can often turn this into a CSRF because most session cookies are set with ‘SameSite=Lax’ (default in both Chrome and Firefox), meaning cookies are automatically passed within cross-site GET requests, but not POST requests.

CORS also should not be an issue here because our request does not qualify as ‘complex’, which means that CORS will not block the request – it will block the response.

For CORS to qualify a request as ‘complex’ it must meet one of these requirements:

  • A request that uses methods other than GET, POST, or HEAD
  • A request that includes headers other than Accept, Accept-Language or Content-Language
  • A request that has a Content-Type header value other than application/x-www-form-urlencoded, multipart/form-data, or text/plain

If just one of the above cases is met, CORS will block the request from going through.

Note: if the application uses a CSRF token on the GET request, you could be stopped unless you find a CORS misconfiguration and retrieve the token. See number 2 for more details on that. You also need to make sure SameSite is not set to ‘Strict’, which means no cookies are attached in cross-site GET requests

Find an application with a CORS misconfiguration and a session cookie explicitly set with SameSite=None

This is a rare find but would allow you to send a cross-site request with POST data to the application via JavaScript. By ‘CORS misconfiguration’ I am referring to the attacker’s ability to control the ‘Access-Control-Allow-Origin’ response header and bypass CORS restrictions (for the sake of the example, I am also assuming ‘Access-Control-Allow-Credentials’ is set to ‘true’ as well), allowing them to read the server response.

You might be thinking, why not just set the ‘Origin’ request header through JavaScript? This will not work because browsers do not allow you to set the ‘Origin’ header, you will get a forbidden error if you try.

The SameSite flag being set to None allows cookies to be automatically attached to cross-site POST requests. If the SameSite flag is not included when setting the cookie, Firefox and Chrome will automatically make it ‘SameSite=Lax’ which is why it must be explicitly set to ‘SameSite=None’ for this to work.

Find a Cross-Site Scripting vulnerability (my personal favorite)

This is the most common and cleanest way to pull off a modern-day CSRF. Since XSS allows you to execute JavaScript within the same origin of the site, you should have no CORS issues and no problem having cookies auto-attach to requests, regardless of the SameSite status.

Even if the site is using a CSRF token, you could grab that from the page and include it within the state-changing request. This is one of the reasons why XSS is so dangerous, but unfortunately often overlooked.

Final Thoughts

Cross-Site Request Forgery is still a valid and existing vulnerability in today’s Application Security landscape. Since it can be a complicated vulnerability, it is highly recommended to conduct a thorough penetration test of your application to ensure you are not vulnerable to one of the three above methods.

Are you ready to get started?