Cross Site Request Forgery
Cross Site Request Forgery (CSRF) is an attack where an attacker can trick a user's browser into performing actions on the attacker's behalf. This has the added benefit of taking advantage of the user's authentication. The archetypal example of CSRF is to imagine that if a bank customer wanted to transfer funds, they would have to visit a specific URL such as, http://bank.com/?transfer.php?to=hacker_acct&amount=1000. Then, all the attacker would have to do is trick people into clicking a link for that URL so that the victim's browser performs a GET and, if the victim happens to be logged into that bank, the victim will unknowingly transfer money to that attacker. The web application is going to assume that the user is in full control of its own actions and will execute the transfer. CSRF is about exploiting the trust that the web application has in the user's browser. You can read more about CSRF here.
CSRF Mitigation
The majority of CSRF mitigation strategies revolve around some sort of nonce being associated with the request being made. That can mean that instead of a dumb URL such as http://bank.com/?transfer.php?to=hacker_acct&amount=1000, you would have http://bank.com/usersession-1234?transfer.php?to=hacker_acct&amount=1000 so that the attacker could not generate the link ahead of time. Another example of this when performing a POST is to add a hidden field set to a nonce. This token will get passed along when the user hits the submit button and the server will check that the nonce it set for that form is what was submitted. Like before, this nonce can't be pre-generated, and thus an attacker is unable to create a dumb link to trick users with. Here is what a CSRF token looks like:That token prevents us from hard coding a POST to the URL since the value of that token should change each and every time the form is loaded.
Mitigating CSRF Mitigations
With these tokens and nonces making the URL or parameters unique, CSRF should pretty much be resolved because the attacker is not able to perform any actions right? Not quite. Let's review what XSS provides for us. XSS allows an attacker to run a script on a victim's browser. The victim's browser is going to trust that the script is safe and will execute, no questions asked. We can use an XSS vulnerability to execute code that will gather the necessary information to overcome the CSRF protections in place. In other words we use the XSS vulnerability to determine what the specific session information or token is, incorporate that into a CSRF attack, and proceed as a normal.
Putting It All Together
Let's go back to a previous post. What we had there was a XSS vulnerability in the body of an email. With that in mind, let's go looking around the web application a little more to see what we can find. Within the Advanced Options, we see that there is an option to configure the password reset question, answer, and a checkbox to enable the feature at all.
Let's go fill this out, hit submit, and trap the request with a Firefox plugin, named Tamper Data, that the browser makes so we know what we have to replicate.
Here we see the POST that is made once we update these values and hit Save:
Tamper Data is showing us on the right hand side all of the parameters that are being passed to the URL. Of particular interest, we see that enabling the password reset question corresponds to the usepassresetting parameter having a value of checkbox and you can also see the URL encoded password reset question and the password reset answer. The other parameters are important as well and will play a part later.
The other important thing to realize is that another parameter that gets passed along is the id parameter that has a value of 333n487v6y1sJjJ0GFnzPsID8oKJBfmEZeyk20140130002922. If you log in and out a few times you will come to notice that this is probably a random value. I did not expend any time doing a statistical analysis with Burp to verify this but I assumed it was. This id parameter is what will stop us from being able to hardcode a POST to _processaccountoptions with usepassresetting set to checkbox and passresetanswer set to whatever we want. Fortunately, we can get around this thanks to the XSS vulnerability we have in our backpocket.
The flow of the attack will go as follows, the victim opens an email with JavaScript embedded in the body of the email. This JavaScript snippet will call a piece of JavaScript on the attacker's server that will:
- Parse out the value of the id parameter in the URL of the victim's browser
- Use that id parameter value and complete the POST request to set the victim's password reset question.
Now, we will send an email to the victim with this embedded into the body of the email:
That will then call this piece of JavaScript that will be on the attacker's server:
This script will first grab the URL and then proceed to parse out the value of the id parameter by performing a substring. Next, it then calls the passwordReset function and that will piece together the parameters necessary to perform a proper POST to the _processaccountoptions URL. Notice that this sets the usepassresetting, passresetquestions, and passresetanswer.
This should be enough to bypass the randomly generated id and if everything works, when a user opens the malicious email they will unknowingly enable the password reset feature and set their password reset answer to whatever the attacker chose. This will then allow the attacker to set a user's password by using the password reset feature.
Thus when the user opens the email the attacker can:
This script will first grab the URL and then proceed to parse out the value of the id parameter by performing a substring. Next, it then calls the passwordReset function and that will piece together the parameters necessary to perform a proper POST to the _processaccountoptions URL. Notice that this sets the usepassresetting, passresetquestions, and passresetanswer.
This should be enough to bypass the randomly generated id and if everything works, when a user opens the malicious email they will unknowingly enable the password reset feature and set their password reset answer to whatever the attacker chose. This will then allow the attacker to set a user's password by using the password reset feature.
Thus when the user opens the email the attacker can:
- Go to the webmail login screen and click the Forgot your password? link
- Enter the victim's email address
- And we should see that the victim will have their password reset question set to what we set it to be in our script, "Hacked via XSS"
- From there the attacker can input the answer to the question as, 'h4cked', and then set a new password for the user. Heck, you could probably do step 3 and 4 by extended the script to do another CSRF POST to save you the manual effort.
I hope this post helped describe what CSRF is and what it allows you to do and just how powerful XSS can be and how its impact can be much more than just dumping cookies and throwing alert boxes.