Exploiting POST-Based CSRF

This article will explore a variety of methods to identify, chain and exploit POST-Based CSRF to maximize the severity of your findings.

What Is POST-Based CSRF?

POST-Based CSRF, as opposed to GET-Based CSRF, is a type of CSRF which affects POST requests. These, unlike GET requests, contain a body which means they cannot be exploited simply using an image. Instead, one must create a specially crafted page in order to execute the CSRF. This is where a lot of newer hackers fail, as they are not aware that this is possible, so it’s something that’s very important to be familiar with!

The Login CSRF Mistake

Logout CSRF is not accepted as a valid submission in a lot of bounty programs, and for a very good reason. However, a lot of bounty programs mistakingly inlude login CSRF under the same umbrella. While the severity of login CSRF is generally pretty low, it can be easily used in a chain attack to convert self XSS into stored XSS. Imagine a scenario where you identify self XSS on victim.com, another vulnerability which is usually out of scope due to the unlikely user interaction required to execute a payload (self XSS, generally speaking, will require the user themselves to insert the payload, arguments have been made that users could be convinced into doing so, but naturally users could be convinced to insert payloads into their browser console all the same, which would have the same desired effect). So these are 2 vulnerabilities which are “worthless” according to the majority of vulnerability disclosure programs. You find this self XSS on somerandompage.php and notice there is no CSRF token, or other anti-CSRF measure, on the login form (login.php). Firstly, you must register an account on the website (we’ll create an account called user with the password pass) and next, you should insert the payload on somerandompage.php. Now whenever YOU visit that page, the code will execute. In fact, whenever anyone at all who is logged into your account sees that page, they too will execute the payload. Next, we must create a page exploiting the login CSRF in order to automatically log your victim in. You then create your own website evil.com and include the following PoC source code:

<!-- This is a HTML comment -->

<!-- Create a form pointing to the login page using the POST protocol -->
<form action="https://victim.com/login.php" method="POST">
<!-- Automatically fill the username -->
<input name="username" value="user">
<!-- Automatially fill the password -->
<input name="password" value="pass">
<!-- Create a login button with ID btn -->
<input type="submit" id="btn">
<!- Close the form -->
</form>

<!-- Now we must automatically execute the form when a user visits our site, using javascript -->
<script>
//This is a javascript comment
//Simply click the button with ID btn
document.getElementById("btn").click();
//End of script
</script>
<!-- Whenever a user visits this page, they will automatically login to your account -->

So that’s cool and all, but we still haven’t actually got the user to visit somerandompage.php to execute the payload. It seems as though they must automatically visit this, or we have to yet again convince them to click another link, which of course would decrease the severity. This is not the case though! I’ve been experimenting with this recently, to improve the impact of some similar vulnerabilities I’ve discovered and have been creating a second page on the website evil.com and automatically opening it up in a new tab once a user visits the first page, and then waiting some time (using javascript) before redirecting to somerandompage.php should work. There are multiple solutions for this, but it feels elegant to wait a few seconds (while the POST request executes) before doing a redirect. This should then redirect them to the page (using the cookies they now have) and execute the payload.

The ‘Anonymous Forms’ CSRF Mistake

You might have figured by now, that when exploiting POST-Based CSRF to get us XSS, we tend to primarily focus on CSRF classes which are out-of-scope. This is because we know that the only reason these are out-of-scope, is because they exist. So, if we find Self XSS, similar to above, in one of these ‘anonymous forms’ (which just means you don’t have to be logged in to use it/it is in no way connected to your account), then we are easily able to exploit this to get XSS using the same method mentioned above.

Identifying POST-Based CSRF

I think before we move any further into the world of POST-Based CSRF, that’s it’s critical I mention how we actually identify this. A lot of new hackers will make some obvious mistakes here, which will lead them to wasting valuable time on an endpoint which is not vulnerable. There’s a few ways websites protect against POST-Based CSRF.

CSRF Tokens

You will see these tokens in the body of the request. This is where the data is being sent for the POST request. You’ll see it look something like this:

xyz=123&username=you&password=yourpassword&csrf_token=157be8b852cb6dd8536cb4d662718825

The first 3 parameters xyz, username and password could literally be anything, but it’s the csrf_token that we care about. Remember, this could be literally anything. If you see this, it doesn’t mean it’s not vulnerable! Try omitting it, or removing a single character (what I do). Sometimes they will check that the parameter is set, but forget to check the value of it!

CSRF Headers

Some websites utilize headers for their CSRF tokens. It’ll look something like: X-CSRF-Token and will contain another string. I recommend for testing this, to remove all ‘non predictable’ parameters from both the body & headers of the request. Cookies are an exception, as the browser automatically accepts this. Every ‘static’ parameter you can add to your exploit script (for the body). The header, you really can’t modify, so you’re going to want to remove everything that the browser doesn’t automatically place there from the intercepted request!

Referer Headers

The referer header (which humourously misspells ‘referrer’), is another method I encountered recently which actually prevented CSRF. However, the website in question didn’t validate that the referer header was coming from the same origin. The browser will automatically add the origin of our exploit script to the referer header when we actually use the exploit script I posted above! So that actually bypassed the protection for me.

The End

Now that you know what POST-Based CSRF is, how to exploit it, why we care about it & how to get those valuable bounties from it, I think it’s time to end this post. If you have any questions, feel free to message me on twitter @LooseSecurity. I’m always happy to help! Thanks for reading & I hope you learned something new from this article.

Written on May 23, 2019