2.5. Cross-Site Request Forgery
Cross-Site Request Forgery (csrf) is an attack method that allows attackers to send arbitrary HTTP requests through victims. The victim referred to here is an uninformed accomplice, and all forged requests are initiated by him, not the attacker. In this way, it is difficult for you to determine which requests belong to cross-site request forgery attacks. In fact, if you do not specifically prevent cross-site request forgery attacks, your application may have vulnerabilities.
Please refer to the following simple application, which allows users to buy pens or pencils. The Interface contains the following form:
Code:
<Form action = "buy. php" method = "Post">
<P>
Item:
<Select name = "item">
<Option name = "pen"> pen </option>
<Option name = "penpencil"> penpencil </option>
</SELECT> <br/>
Quantity: <input type = "text" name = "quantity"/> <br/>
<Input type = "Submit" value = "buy"/>
</P>
</Form>
An attacker will first use your application to collect some basic information. For example, the attacker first accesses the form and finds two form elements, item and quantity. He also knows that the value of the item will be a pencil or a pen.
The following buy. phpProgramProcess the form submission information:
Code:
<? PHP
Session_start ();
$ Clean = array ();
If (isset ($ _ request ['item'] & isset ($ _ request ['quantity '])
{
/* Filter input ($ _ request ['item'], $ _ request ['quantity ']) */
If (buy_item ($ clean ['item'], $ clean ['quantity '])
{
Echo '<p> thanks for your purchase. </P> ';
}
Else
{
Echo '<p> there was a problem with your order. </P> ';
}
}
?>
Attackers will first use this form to observe its actions. For example, after buying a pencil, the attacker knows that a thank-you message will appear after the purchase is successful. With this in mind, attackers will try to access the following URL to submit data in the get mode for the same purpose:
Http://store.example.org/buy.php? Item = Pen & quantity = 1
If successful, attackers can now obtain the URL format that can be purchased when a legitimate user accesses the website. In this case, Cross-Site Request Forgery is very easy, because the attacker only needs to cause the victim to access the URL.
Although there are multiple methods to initiate cross-site request forgery attacks, the method of embedding resource fragments is the most common. To understand the attack process, it is necessary to first understand how browsers request these resources.
When you access the http://www.google.com (Figure 2-1), your browser will first request the resource identified by this URL. You can view the returned content of the request by viewing the source file (HTML) of the page. After the returned content is parsed in the browser, the Google logo image is found. The image is represented by the IMG tag of HTML, and the src attribute of the tag represents the URL of the image. The browser then sends a request to the image. The difference between the two requests is that the URL is different.
Figure 2-1. Google Homepage
A csrf attack can use an IMG tag to leverage this behavior. consider visiting a web site with the following image identified in the source:
Based on the above principle, cross-site request forgery attacks can be achieved through the IMG tag. Consider if the followingSource codeWhat will happen to the webpage:
Because the buy. php script uses $ _ request instead of $ _ post, every user who logs on to the store.example.org store will request the URL to purchase 50 pencils.
The existence of Cross-Site Request Forgery attack is one of the reasons why $ _ request is not recommended.
The complete attack process is shown in Figure 2-2.
Figure 2-2. Cross-Site Request Forgery attacks caused by images
When an image is requested, Some browsers change the accept value in the request header to give the image type a higher priority. Protection measures are required to prevent this situation.
You need to take several steps to mitigate the risk of cross-site request forgery attacks. The general steps include using the POST method instead of using get to submit a form, using $ _ post instead of $ _ request when processing the form submission, and performing verification during important operations (the more convenient, the greater the risk, you need to strike a balance between convenience and risk ).
Any form to be operated must use the POST method. There is a description in section 9.1.1 of RFC 2616 (HTTP/1.1 Transfer Protocol,:
"In particular, The get and head methods should not be used to initiate an operation, but only to obtain information. These methods should be considered 'security. The customer's browser should use special methods, such as post, put, or delete, to make users realize that the operations being requested may be insecure ."
The most important thing is that you must be able to force the use of your own form for submission. Although the data submitted by the user seems to be the result of your form submission, it is suspicious if the user is not calling the form recently. SeeCode:
Code:
<? PHP
Session_start ();
$ Token = MD5 (uniqid (RAND (), true ));
$ _ Session ['Token'] = $ token;
$ _ Session ['token _ time'] = Time ();
?>
<Form action = "buy. php" method = "Post">
<Input type = "hidden" name = "token" value = "<? PHP echo $ token;?> "/>
<P>
Item:
<Select name = "item">
<Option name = "pen"> pen </option>
<Option name = "penpencil"> penpencil </option>
</SELECT> <br/>
Quantity: <input type = "text" name = "quantity"/> <br/>
<Input type = "Submit" value = "buy"/>
</P>
</Form>
With these simple modifications, a cross-site Request Forgery attack must include a valid Verification code to completely mimic form submission. Because the verification code is stored in the user's session, attackers must use different verification codes for each victim. This effectively limits any attacks on a user and requires the attacker to obtain the valid Verification Code of another user. Using your own verification code to forge another user's request is invalid.
This verification code can be simply checked using a conditional expression:
Code:
<? PHP
If (isset ($ _ session ['Token']) &
$ _ Post ['Token'] ==$ _ session ['Token'])
{
/* Valid token */
}
?>
You can also add a valid time limit to the Verification code, such as 5 minutes:
Code:
<? PHP
$ Token_age = Time ()-$ _ session ['token _ time'];
If ($ token_age <= 300)
{
/* Less than five minutes has passed .*/
}
?>
By including the verification code in your form, you have actually eliminated the risk of cross-site request forgery. You can use this process in any form that requires an operation.
Although I use the IMG label to describe the attack method, the Cross-Site Request Forgery attack is just a general term. It refers to the type of attacks that all attackers perform by forging others' HTTP requests. Known attack methods include get and post attacks at the same time. Therefore, do not consider that only the POST method is used strictly.