What is CSRF?

CSRF (Cross-site Request Forgery), also known as one Click Attack/Session Riding (CSRF/XSRF).

What can CSRF do?

You can think of a CSRF attack this way: An attacker steals your identity and sends malicious requests on your behalf. CSRF can do things like: send emails in your name, send messages, steal your account, even buy goods, virtual currency transfer…… The problems include personal privacy leakage and property security.

3. CSRF vulnerability status

CSRF attack was proposed by foreign security personnel in 2000, but it was not noticed in China until 2006. In 2008, CSRF vulnerability was exposed in many large communities and interactive websites at home and abroad, such as: NYTimes.com (The New York Times), Metafilter (a large BLOG site), YouTube and Baidu HI…… Now, many sites on the Internet are so unprepared that the security industry calls CSRF a “sleeping giant.”

4. Principle of CSRF

The following diagram briefly illustrates the idea of a CSRF attack:

As you can see from the figure above, to complete a CSRF attack,The victim must complete two steps in turn:

  • 1. Log in to trusted website A and generate cookies locally.
  • 2. Visit dangerous website B without logging out of A.

Looking at this, you might say, “If I don’t meet one of these two criteria, I won’t be attacked by CSRF.” Yes, it does, but you can’t guarantee that the following won’t happen:

  • 1. You can’t guarantee that once you log in to one site, you won’t open another TAB page and visit another site.
  • 2. You cannot guarantee that your local Cookie will expire immediately after you close your browser and that your last session has ended. (Actually, closing the browser doesn’t end a session, but most people mistakenly think closing the browser is equivalent to logging out/ending the session……)
  • 3. The alleged attack site in the image above may be a trusted and frequently visited site with other vulnerabilities.

I have outlined the idea of CSRF attacks in general. Here I will use several examples to elaborate on specific CSRF attacks. Here I will use a bank transfer operation as an example (just an example, real bank websites are not so stupid :>).

4.1 example 1

Bank web site A, it to GET requests to complete the operation of the bank transfer, such as: www.mybank.com/Transfer.ph…

Dangerous web site B, which contains the following HTML code:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
Copy the code

First, you log on to the bank’s website A, then to the dangerous website B, and oh, that’s when you find that your bank account is missing $1000……

Why is that? The reason is that bank website A violates the HTTP specification by using GET requests to update resources. Before you visit the dangerous website B, you have logged into the bank website A, which is in BRequest third party resources in the form of GET (the third party here refers to the bank website, originally this is A legitimate request, but it is used by criminals), so your browser will bring the Cookie of your bank website A to send A GET request to obtain resources.http://www.mybank.com/Transfer.php?toBankId=11&money=1000“, the bank website server received the request, thought it was an update resource operation (transfer operation), so immediately conducted the transfer operation……

4.2 sample 2

To eliminate the above problems, the bank decided to use POST request to complete the transfer operation.

The WEB form of bank website A is as follows:

<form action="Transfer.php" method="POST">
  <p>ToBankId: <input type="text" name="toBankId" /></p>
  <p>Money: <input type="text" name="money" /></p>
  <p><input type="submit" value="Transfer" /></p>
</form>
Copy the code

The background processing page transfer.php is as follows:

<? php session_start(); If (isset ($_REQUEST [' toBankId] && isset ($_REQUEST [' money '])) {buy_stocks ($_REQUEST [' toBankId], $_REQUEST [' money ']); }? >Copy the code

Dangerous site B, again, just contains the HTML code:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
Copy the code

As in example 1, you log on to the bank’s website A, then to the risk website B, resulting in….. As in example 1, you again lose 1000 ~ T_T. The cause of this accident is: The background of the bank uses $_REQUEST to obtain the requested data, and $_REQUEST can obtain the data of both GET request and POST request, which causes that the background processor cannot distinguish whether it is the data of GET request or POST request. In PHP, you can use $_GET and $_POST to GET data for GET requests and POST requests, respectively. In JAVA, request, which is used to obtain request data, also has the problem of not distinguishing GET request data from POST data.

4.3 sample 3

After the previous two painful lessons, the bank decided to change the method of obtaining the request data to $_POST, and only obtain the data of the POST request. The code of the background processing page transfer.php is as follows:

<? php session_start(); If (isset ($_POST [' toBankId] && isset ($_POST [' money '])) {buy_stocks ($_POST [' toBankId], $_POST [' money ']); }? >Copy the code

However, dangerous B has moved with The Times and changed its code:

< HTML > <head> <script type="text/javascript"> function steal() {iframe = document.frames["steal"];  The iframe. Document. Submit (" transfer "); } </script> </head> <body onload="steal()"> <iframe name="steal" display="none"> <form method="POST" Name = "transfer" action = "http://www.myBank.com/Transfer.php" > < input type = "hidden" name = "toBankId" value = "11" > <input type="hidden" name="money" value="1000"> </form> </iframe>Copy the code

If the user continues with the above operation, unfortunately, the result will again be no 1000…… Because here dangerous website B secretly sent a POST request to the bank!

To sum up the above three examples, the main attack modes of CSRF are basically the above three, among which the first and second are the most serious, because the trigger condition is very simple, a is enough, while the third is more troublesome, and requires JavaScript, so the chance of use is much less than the previous, but no matter which case, Whenever a CSRF attack is triggered, the consequences can be serious.

Understanding the above three attack modes, you can actually see that the CSRF attack is an implicit authentication mechanism derived from the WEB! The WEB’s authentication mechanism can guarantee that a request is from a user’s browser, but it can’t guarantee that the request is user-approved!

5. CSRF defense

I summarized the information I saw, CSRF defense can be started from the server side and the client side, the defense effect is better to start from the server side, now the general CSRF defense is also carried out in the server side.

The CSRF method of the server side is very diverse, but the general idea is the same, that is, to increase the pseudo random number in the client page.

5.1 Cookie Hashing(All forms contain the same pseudo-random value)

This is probably the simplest solution, to write a token to a cookie and then attach the token via query, body, or header at request time. The request arrives at the server, checks the token, and if it is correct, it must be a request from the local domain that can see the cookie. CSRF cannot do this. Because an attacker cannot (in theory) obtain a Cookie from a third party, the data in the form fails to be constructed

<? $value = "DefenseSCRF"; Setcookie (" cookie ", $value, time () + 3600); ? >Copy the code

Add a Hash value to the form to verify that the request was actually sent by the user

<? php $hash = md5($_COOKIE['cookie']); ? > <form method= "POST" action= "transfer. PHP" > <input type= "text" name= "toBankId" > <input type= "text" name= "money" > <input type= "text" name= "money" Type = "hidden" name = "hash" value = "<? =$hash; ? > "> <input type=" submit "name=" submit "value=" submit ">Copy the code

Then Hash value authentication is performed on the server side

<? php if(isset($_POST['check'])) { $hash = md5($_COOKIE['cookie']); if($_POST['check'] == $hash) { doJob(); } else { //... } } else { //... }? >Copy the code

In my opinion, this method has prevented 99% of CSRF attacks, and 1%…. Since users’ cookies are easily stolen due to XSS vulnerabilities on the site, this is another 1%. Most attackers will give up when they see a Hash value, except for some, so this is not the best method if 100% elimination is required.

5.2 authentication code

The idea is that each user submission requires the user to fill in a random string on the image in the form, e…. This solution can completely solve CSRF, but I think it is not very good in terms of ease of use. I also heard that the use of captcha images involves a Bug called MHTML, which may be affected in some versions of Microsoft IE.

5.3 One-time Tokens(Different forms contain a Different pseudo-random Value)

In realizing One-time Tokens, you need to pay attention to “Parallel session compatibility”. If a user has two different forms open on the same site at the same time, CSRF protection should not affect his submission of any form. Consider what would happen if the site generated a pseudo-random value to override the previous pseudo-random value each time a form was loaded: the user can only successfully submit the form he opened last, because all the other forms contain illegal pseudo-random values. Care must be taken to ensure that CSRF protection does not affect tabbed browsing or browsing a site with multiple browser Windows.

Implementation steps: 1). First, the token generating function (gen_token()) :

<? PHP function gen_token() {// Use a random number from Rand() as a token. // Random Object created and used only once $token = MD5 (uniqid(rand(), true)); return $token; }Copy the code

2). Then the Session token generator (gen_stoken()) :

<? php function gen_stoken() { $pToken = ""; If ($_SESSION[STOKEN_NAME] == $pToken){$_SESSION[STOKEN_NAME] = gen_token(); } else{// continue with the old value}}? >Copy the code

3).WEB forms generate functions that hide input fields:

<? php function gen_input() { gen_stoken(); Echo "< input type =" hidden "name = \ \" ". FTOKEN_NAME. "\" value = \ "", $_SESSION [STOKEN_NAME]." \ ">"; }? >Copy the code

4).WEB form structure:

<? php session_start(); Include (" functions provides. PHP "); ? > <form method= "POST" action= "transfer. PHP" > <input type= "text" name= "toBankId" > <input type= "text" name= "money" > <? gen_input(); ? > < form name= "submit" value= "submit" > </form>Copy the code

5). Server check token: this is simple, I won’t bother here. This does not fully comply with the “parallel session compatibility” rule, so you can modify it accordingly.

reference

Front-end network security Required 1 Same-origin policy and CSRF Describes the CSRF attack modes