When you are browsing a website, it is typical for that website to request data from another website on your behalf. For example, in most
While all the above use cases are necessary for a good browsing experience, they might also be a source of a security problem, because the website you are browsing can request your web browser to retrieve data from another website without your consent. If such requests are not handled correctly, an attacker can launch a Cross-Site Request Forgery attack.
How Can Cross-Site Request Be Dangerous?
When a website requests data from another website on behalf of a user, as long as the request is an unauthenticated one, i.e. the session cookie is not sent, there are no security concerns. Though when the user’s session cookie is sent with the request, an attacker can launch a Cross-Site Request forgery attack, which abuses the trust relationship between the victim’s browser and the web server.
In this article, we will highlight the dangers that arise from this browser behaviour and how an attacker can take advantage of it and carry out a Cross-Site Request Forgery attack. In order to be able to understand how Cross-Site Request Forgery works, one must understand what HTTP requests and cookies are, so let’s start with a quick introduction of them first.
A Quick Introduction to HTTP Requests & Web Cookie
GET and POST HTTP Requests
HTTP GET Request
A HTTP GET request is when you request a web server data. Example; when you enter the URL in the web browser you instruct the browser to send a HTTP GET request to the web server on which the website is hosted, so the web server in return sends the response for the browser to render it.
HTTP POST Request
Automatically Generated HTTP GET and POST Requests
Web and Session Cookies
How Does Cross-Site Request Forgery Work?
Since cross-site requests do not need your permission, an attacker can abuse this and send requests without your consent and without you noticing. Let’s take a look at the following scenario which highlights why this can be a problem:
A Short Introduction to Web Forms
Imagine a form on a website that allows you to change your email address. To change it, all you have to do is write your new address into an input field and click on "change" while you are logged in. If you are not logged in, i.e. you do not have a session cookie the form would not work. Let’s see how this input field works by looking at the underlying HTML code:
<p>Your new email address</p>
<form method = "POST" action = "mail.php">
<input type = "text" name = "email" placeholder = "Change your email address">
<button type = "submit">change</button>
Under the hood
In the web form code above there are three important HTML attributes; method, action and name.
The method Attribute
The method HTML attribute is used to specify which HTTP verb to use, and by
Such requests are logged in the web server’s log files and in the browser history. Therefore the GET verb should only be used to transmit non-sensitive information and for actions that don't change data (insert, update, delete etc.), such as an indicator of the current page you are browsing; ?page=home.
In web forms typically the HTTP verb POST is
The action Attribute
The second HTML attribute is called
The name Attribute
The name attribute in the web form’s input field that contains the name of the parameter in which the data you submit will be stored. Therefore if you type in firstname.lastname@example.org in the form and click the submit button, the value of the parameter mail will be
The HTTP POST Request
Upon submitting this form, the browser sends the below HTTP request:
POST /email.php HTTP/1.1
As you can see there is a Host HTTP header containing the hostname of the website the form is submitted to. There is also a Cookie HTTP header containing the session cookie, which the web application uses to determine whether or not you are logged in etc.
Abusing Web Forms in a Cross-site Request Forgery Attack
My new email address
Create a Copy of the Web Form
With the above knowledge, it is easy to think of a scenario in which an attacker can change your email address to something of his choice. He can copy the web form and host it on his own web server, such as http://www.attacker.com/evil.php. Below is an example of the new form:
<form id = "csrf_form" method = "POST" action = "http://example.com/email.php">
<input type = "text" name = "mail" value = "email@example.com">
From the code above you can also notice that the form does not have a Submit button, so the attacker can trigger the web form without your knowledge and consent.
The Attacker’s HTTP Request
The below is the HTTP Post request that was generated by the attack. We’ve removed some unrelated request headers so it is easier to read:
POST /email.php HTTP/1.1
Here is a breakdown of the attacker’s HTTP Post request:
- The browser issues a POST request
- The host is the vulnerable website the user is logged in to, in our case example.com. Note the referrer and origin header, which shows from where the request is coming, i.e. attacker.com.
- The Cookie header, which contains the user’s session cookie. Even though the browser request was initiated by a malicious script, the browser still sends the Cookie header along with the request because the request is for example.com, for which the user has a session cookie. This also means that the web application will recognize the user’s logged in session.
- Below the
cookieheader is the Content-Type HTTP header, which shows that the request was issued by a form.
- And at the bottom is the post body, the parameter-value pair. The parameter is mail and the value is the attacker’s set one, firstname.lastname@example.org.
Tricking Victims Into a CSRF Attack
How can attackers trick their victims into a CSRF attack? Let’s assume the attacker publishes the form on https://attacker.com/csrf.html. All he needs to do is trick the user to navigate to that URL, which is typically done by encouraging the victim to visit the URL via an email.
So once the victim visits https://attacker.com/csrf.html the form submission is triggered. The vulnerable website https://example.com accepts the request and the
Now all an attacker has to do is using the "password reset" functionality to send a password reset
Hiding the CSRF Attack from the Victim
For the victim not to notice the CSRF attack, the attacker can create another web page called info.html, which contains information about a topic the victim is interested in. However, the web page can contain a hidden iframe pointing to https://attacker.com/csrf.html, so once the victim visits info.html, the form on csrf.html is automatically triggered, without any visible indicator to the victim.
Attackers typically use CSRF attacks on password or email change forms, to hijack their victims’ accounts, or to create a new admin user on a web application.
Preventing Cross-Site Request Forgery Attacks
An attacker can launch a CSRF attack when he knows which parameters and value combination are being used in a form. Therefore by adding an additional parameter with a value that is unknown to the attacker and can be validated by the server, you can prevent CSRF attacks. Below is a list of some of the methods you can use to block Cross-Site Request Forgery attacks:
Implement an Anti-CSRF Token
This is a random string that is only known by the user’s browser and the web application. It is usually stored
If the value of the session variable and the hidden form field match, the web application accepts the request. If they do not match the request is dropped. Since in this case, the attacker does not know the exact value of the hidden form field that is needed for the request to be accepted, he cannot launch a CSRF attack.
Use the Same-Site Flag in Cookies
The Same-Site Flag in Cookies is a relatively new method that is being used to prevent CSRF attacks. In the above scenario, we saw that https://attacker.com/ could send a POST request to https://example.com/ together with a session cookie. This session cookie is unique for every user and the web application uses it to distinguish different users from each
If the session cookie is marked as