Protection Against Cross Site Attacks
- Introduction to Hacking
- History of Cryptography
- Why Privacy Matters
- Supercookies in the Wild
- Ultimate Guide to SSL for the Newbie
- How Internet Security and SSL Works
- Man in the Middle Hacking and Transport Layer Protection
- Cookie Security and Session Hijacking
- What is Cross Site Scripting? (XSS)
- What is Internal Implementation Disclosure?
- Parameter Tampering and How to Protect Against It
- What are SQL Injection Attacks?
- Protection Against Cross Site Attacks
What is Cross Site Scripting?
Cross Site Scripting (XSS) are typically carried out against authenticated users and involve the user performing an action on the attacker's behalf.
There isn't much value is getting an unauthenticated user to perform an action, but huge value if you can get an authenticated user to. A classic example would be for a victim to authenticate to their online bank and transfer money into the account of the attacker. If the victim is authenticated and the attacker can trick the victim into making a request on their behalf, they can carry out the transaction.
The only thing that makes a user authenticated is the authentication cookie, which we have seen before. If this is left vulnerable, it is open as a possible attack vector. As we have seen in previous tutorials, cookies are sent with every request, secure or insecure. If an authentication cookie is transmitted over insecure methods, its contents can be captured and the session hijacked. Even if the cookie is secure, XSS attacks can still leave an application and users vulnerable.
So how do we (as an attacker) trick a victim into making a request which they never intended to which has malicious intent to advantage the attacker?
Cross Site Request Forgery
In order to understand how much of a problem XSS is, we must understand how a user session is authenticated. Since HTTP is a stateless protocol (each request knows nothing about the previous request) cookies are used to maintain state through the use of a session id. This links back to a session on the server, usually a database, so when the request is processed by the server it knows who the user is. The authentication cookie is sent automatically to the website with EVERY request, the website then identifies and authorises the user based on that cookie.
Let's continue the example of an online banking application. We have a user, who has authenticated successfully to the application, they have an authentication cookie. Now, every time they make a request to the server that authentication cookie is sent along to reauthenticate the session. It's not the user doing this though, you are never aware of sending the cookie, it is the browser which does this for you. This is an important distinction because it is the browser that we will be tricking.
What the attacker is aiming to do is to send a malicious request to the server using the users browser. When that request is issued, the cookie will, of course, be sent along with it. All of this happens against a legitimate website, with a legitimately constructed request it's just that the request is one the user didn't intend.
How to Trick a User
Let's start off by looking at a real example of how a cross-site scripting attack could be added to a legitimate website. In 2012, the Twitter account of Lady Gaga was hacked, and a malicious link added to the Twitter feed. Many attacks come from reputable sources such as Twitter and Facebook, sites where attackers can share links. The attacks are based on the user following a link to the attacker's website, which mounts the attack.
So here is a nice little enticement. A free Macbook! It looks legit, the source is Lady Gaga so it can't possibly be bad! Right? So the user goes ahead and clicks the link. They are then sent to the attacker's website, which will probably be styled to look like an authentic page and use a similar domain name, but one which they control, for example, mapple.com Very similar, but totally different.
The attacker's page will then get the user to perform an action, typically filling in a form and clicking a button.
How this Works
Now, on the attacker's page, the user will be presented with a form and a button to click. When the button is clicked there is a postback to the server and the contents of the form are sent in that post request. In the hackers page, however, the form post URL is to the online banking transfer of funds address, and the form controls constructed in such a way as to send the correct form data which the banking page needs, and the browser will automatically attach the authentication cookie. As far as the banking server is concerned, it just received a request to transfer funds, from the victim's browser, using a valid authentication cookie so it goes ahead and processes the transaction.
So what does the form structure look like?
- <form action="http://www.myonlinebank.com/transfer" method="POST" target="hiddenFrame">
- <input type="hidden" name="targetAccount" value="6365584" />
- <input type="hidden" name="amountToTransfer" value="99.99" />
- <input type="submit" value="Win an iPad" onclick="alert('You Won!!!')" />
- <iframe name="hiddenFrame" style="display:none;visibility:hidden"></iframe>
In this form, contained on the attacker's website, the form is going to post all the values to the online bank transfer address. It is going to pass two parameters the account of the attacker, and the amount to transfer. When the button is clicked the request is sent to the online banking application together with the authentication cookie and the funds transferred. To prevent the user from seeing what is happening, the request is sent to the hidden frame.
This is an overly simplified example, but it serves to show how an attack could be constructed. It relies on the user being pre-authenticated to the banking website, clicking a link from an external source to the attacker's website and then completing the action. So this introduces a new attack vector to the mix, that of tricking the user. This is called social engineering, and we'll look at this in the next tutorial.
The attack we just saw is so prevalent and so easy because the attack relies on a very specific, known pattern. The attack merely replicates exactly what the actual application would do, the attacker just controls the values in the POST request.
So how can we mitigate against CSRF attacks? The only real protection against CSRF attacks is through the use of an anti-forgery token. This token is used to ensure that the authentication cookie and the form POST request match up.
The server will add a hidden field to the legitimate form containing a token, that token is also paired with another token added to the authentication cookie. The attacking website has no access to this token and therefore no means to replicate it in the form submit. When the form is submitted, the server first checks to see if the request contains the anti-forgery token, if it does it checks it matches the contents of the authentication cookie. Only if the two match will the transaction be completed.
Anti-forgery tokens add randomness to the request pattern. The attacker does not have access to the token, therefore, cannot submit the token in a hidden field. The cookie provides verification of the token in the hidden field.