Each year, Rapid7 penetration testers complete hundreds of internally and externally based penetration testing service engagements. This post is part of an ongoing series featuring testimonials of what goes on beneath the hoodie. For more insights, check out our 2020 Under the Hoodie report.
Cross-site request forgery attacks trick web application users into submitting requests that take actions through their session, such as sending someone a phishing link that would automatically submit a form that adds a new user to their web application.
One way to address CSRF attacks is to implement an anti-CSRF token, such as a hidden form field with a random value that gets validated by the server.
While testing one web application, we discovered that the anti-CSRF token was a session cookie that was set in the browser when the user logged in. That was promising, since the browser would add it to the requests for us. The big question was whether matching the value would be difficult. However, we discovered that the server accepted any anti-CSRF cookie value that was present and was the correct length. So, while the web application had an anti-CSRF token, that token wasn't actually being validated in any useful way by the server. The value didn't matter, so we could just supply our own (provided it was the right static length).
Reviewing some of the functions for our admin-level user, we picked the request for submitting password resets for a target user. After creating our own page that would submit the password reset request for a test account, we loaded it in our admin user's browser, and it successfully triggered a password reset.
When our test account got the password reset email, it got even more interesting. The web application used subdomains for each customer organization, and the subdomain in the email had been replaced with the hostname used in our CSRF page. The web application was basing the URL on the "Referer" header, so we were able to manipulate the URL sent to the user.
We crafted a phishing page to look like the web application's password reset page, and set it up so that it would actually send the new password to the target web application and properly set it for the user. This way, we were able to use the CSRF attack to phish a password reset for our target user, and collect that new password, while keeping the compromise quiet by legitimately sending the new password to the real application for them.
The big issue here with the link manipulation had been allowing link URLs to be manipulated based on user inputs, like the "Referer" header. But as far as the CSRF attack goes, it was a good example of not only requiring your web applications to provide anti-CSRF tokens, but testing them to be sure they're actually doing what they're supposed to do.
More in this series:
- This One Time on a Pen Test: Playing Social Security Slots
- This One Time on a Pen Test: I’m Calling My Lawyer
- This One Time on a Pen Test: Outwitting the Vexing VPN
- This One Time on a Pen Test: Ain't No Fence High Enough
- This One Time on a Pen Test: I Know...Everything
- This One Time on a Pen Test: Doing Well With XML