Cross-Site Request Forgery
1. What is cross-site Request Forgery (CSRF)
CSRF (Cross-site request forgery, also known as "One Click Attack" or Session Riding, usually abbreviated as CSRF or XSRF, is a type of malicious use of websites. Although it sounds like XSS, it is very different from XSS, and the attack method is almost different. XSS uses trusted users in the site, while CSRF uses trusted websites by disguising requests from trusted users. Compared with XSS attacks, CSRF attacks are often less popular (so the resources to prevent them are quite scarce) and difficult to prevent. Therefore, XSS attacks are considered to be more dangerous than XSS attacks.
The above is the concept from Baidu encyclopedia. The following is a simple example:
XSS: If XSS is not prevented, I enter <script> while (1) alert ("Haha") </script> in the comment area of the article and submit it successfully. The next time you come in, a dialog box pops up, making the page unable to be browsed normally. if the content is output by the user, then Html Encode should be implemented. The above script will be displayed in the form of common text. In addition, the attack script can read the user's cookie information and do anything that the script can do.
CSRF: Unlike XSS, CSRF uses the current trusted users to allow users to submit data by themselves. For example, user B uploads an image in the post comment area of user A, for example:
[Img] Quit
Then change it:
[Img] http: // Another/Forgery.html [/img]
This is an invalid image and comes from another site. In Forgery.html, the counterfeiter creates a form and the action points to the page to be attacked. The form is automatically submitted when window. onload is executed.
When user A accesses this page, it initiates A request to Another/Forgery.html. Because Web authentication information is usually stored in browser cookies, and each cookie is submitted to the server with the request, this request will submit the cookie and Forgery.html form information together to the server. The server verifies the Cookie and considers it a normal request to perform related operations.
2. Simulate an attack
Based on the above ideas, we will simulate an attack. Create an mvc project on two pages: one for displaying user names and comments, and the other for modifying user names. This is just for demonstration. Here we have a fixed user: James. For example:
Public class CurrentUser {private static CurrentUser currentUser = new CurrentUser () {Name = "zhangsan"}; public string Name {get; set ;} public static CurrentUser Current {get {return currentUser ;}}}
The displayed page is:
Another page on this site is used to modify the User name:
<Div> modify user information: </div> <form action = "/home/update" method = "post"> <p> <label> User Name: </label> <input name = "name"/> </p> <input type = "submit"/> </p> </form>
The corresponding Action is Update. To improve security, we mark it with an [HttpPost] feature (in actual cases, authentication is performed and information is modified based on the user ID ). For example:
[HttpPost] public ActionResult Update(string name) { CurrentUser.Current.Name = name; return RedirectToAction("Index"); }
We can see that there is a link in the comment area above, from another site. Its code is very simple, similar to our modification page, as shown below:
<body> <div> <form id="form" action="http://localhost:50025/home/update" method="post"> <input type="hidden" name="name" value="2b" /> </form> </div></body><script type="text/javascript"> window.onload = function () { document.getElementById("form").submit(); }</script>
As you can see, the action displayed on this page points to the modification page of the previous site, and is automatically submitted after the page is loaded. What will happen when James clicks this link? As follows:
3. How to Prevent
3.1 early prevention
Never trust the data submitted by the user. We usually verify user input in the front and back ends to ensure data correctness and security. For example, if the user uploads an image and then modifies it to The. html format, it should not be saved. We can look at the example of the blog Park. If this is done, it can be saved, but it is displayed in the format of common text, so that the page will not initiate a request to this url when loading. If you look at csdn again, an invalid input prompt is displayed.
Cnblogs:
Csdn:
Of course, this is only the first barrier. Many websites may also be able to enter external links. If users click the link, the website may still be attacked. Therefore, we need further defense.
3.2 MVC practices
We have simulated the CSRF process before, and then we can see how to deal with this situation in MVC.
ValidateAntiForgeryAttribute
This is a Tag feature that inherits FilterAttribute and implements IActionFilter. It can be applied to the Controller or Action. We know that the Filter implementing IActionFilter will be processed before the Action is executed. The specific logic is in the OnAuthorization method of the IActionFilter interface. MVC is verified in this method. How is it verified?
AntiForgeryToken Method
The ValidateAntiForgery feature indicates that the operation needs to be verified. We also need to use the AntiForgeryToken method of HtmlHelper, which is an instance method. This method is called in the View form. This method generates an input den Tag named _ RequestVerificationToken. The value is the anti-counterfeit token. In addition, a cookie with the same name and marked as HttpOnly will be generated, and the value is also an anti-counterfeit token generated through encryption. The OnAuthorization method of the ValidateAntiForgery feature is verified based on these two methods. Specifically:
1. When a user requests this page, the AntiForgeryToken method will generate an input den and cookie, and the values are encrypted Token.
2. the user submits a request. If Action (Controller) marks the ValidateAntiForgery feature, the request is verified.
2.1 If the form does not contain an element named _ RequestVerificationToken, an HttpAntiForgeryException is thrown.
2.2 If there is no cookie named _ RequestVerificationToken, an HttpAntiForgeryException is thrown.
2.3 parse the input and cookie values and determine whether the values match (including the user name and time). If the values do not match, an HttpAntiForgeryException is thrown.
3. When an exception is received, an error page is displayed or yellow pages are thrown.
As for the generation of input values and cookies, mvc encrypts the generation based on the current user name, time, and set MachineKey to ensure that it is not easily guessed. If you are interested, you can learn the detailed process through the source code.
According to the above practice, we add a [ValidateAntiForgery] feature to Update and call the AntiForgeryToken method of HtmlHelper in the form.If a user clicks a link and forgery.html is created and the form is automatically submitted, the cookie will still be submitted. However, if a page is forged, the value of input hidden cannot be known, and thus cannot be verified.
3.3 WebForm practices
WebForm can be directly used without the AntiForgeryToken method. However, after knowing the implementation process of MVC, we can also implement one set by ourselves.
In the page form, like mvc, we also output an input den Tag named _ RequestVerificationToken. The value is the serialized Token, specifically calling the extension method AntiForgeryToken of HttpRespose. The AntiForgeryToken method will not only input hidden, but also store the Guid in Context. item is a set that can be used in each period of a request. After the page cycle is completed, we determine whether this tag exists. If so, we need to write it into the Cookie.
Form:
<form id="Form1" action="UpdateAntiCsrf.aspx" method="post" runat="server"> <div> <%=Response.AntiForgeryToken() %> <input type="text" name="name"/> <input type="submit"/> </div> </form>
AntiForgeryToken extension method:
Public static class HttpResposeExtentions {public static string AntiForgeryToken (this HttpResponse response) {HttpContext context = HttpContext. Current; if (context = null) {throw new InvalidOperationException ("invalid request! ");} Guid guid = Guid. newGuid (); context. items ["_ RequestVerificationToken"] = guid; ObjectStateFormatter formatter = new ObjectStateFormatter (); return string. format ("<input type = 'den den 'name = '_ requestverificationtoken' value = {0}/>", formatter. serialize (guid ));}}
For Token Verification and Writing guids to cookies, it is completed through an AntiCsrfModule. It mainly intercepts the two events before and after page execution. After the page is executed, check whether the GUID needs to be written into the Cookie. Before the page is executed, check whether verification is required and the verification result. If the result does not match, an exception is thrown. The Code is as follows:
Public class AntiCsrfModule: IHttpModule {public void Dispose () {} public void Init (HttpApplication app) {app. preRequestHandlerExecute + = new EventHandler (app_PreRequestHandlerExecute); app. postRequestHandlerExecute + = new EventHandler (app_PostRequestHandlerExecute);} void app_PreRequestHandlerExecute (object sender, EventArgs e) {HttpContext context = (HttpApplication) sender ). context; HttpR Equest request = context. request; IHttpHandler handler = context. handler; if (handler. getType (). isDefined (typeof (ValidationAntiForgeryAttribute), true) {if (request. httpMethod. equals ("POST", StringComparison. currentCultureIgnoreCase) {HttpCookie cookie = request. cookies ["_ RequestVerificationToken"]; if (cookie = null) {throw new InvalidOperationException ("invalid request! ");} String value = request. Form [" _ RequestVerificationToken "]; if (string. IsNullOrEmpty (value) {throw new InvalidOperationException (" invalid request! ");} ObjectStateFormatter formatter = new ObjectStateFormatter (); Guid? Guid = formatter. Deserialize (value) as Guid ?; If (guid. HasValue & guid. Value. ToString () = cookie. Value) {return;} throw new InvalidOperationException ("invalid request! ") ;}} Void app_PostRequestHandlerExecute (object sender, EventArgs e) {HttpContext context = (HttpApplication) sender). Context; Guid? Guid = context. Items ["_ RequestVerificationToken"] as Guid ?; If (guid. hasValue) {HttpCookie cookie = new HttpCookie ("_ RequestVerificationToken", guid. value. toString (); cookie. httpOnly = false; context. response. cookies. add (cookie );}}}
For pages to be verified, use a ValidateAntiForgeryAttribute feature tag, as shown below:
public class ValidateAntiForgeryAttribute : Attribute { }
Similarly, we simulate an attack as before. As we think, the results will throw Yellow Pages.
3.4 Ajax
We have submitted the data in the form of a Post form. What if I submitted the data in ajax? We can determine whether the request is an Ajax request in the background. If not, the operation is not allowed. Because js is restricted by the same-origin policy, scripts cannot communicate with the same domain without being authorized by another domain. That is, Another/Forgery.html can submit data to our background in the form of post, but it cannot submit data in the form of ajax, or call our page methods or access dom elements.
4. Implementation of the blog Garden
The example is around. We can see the "set basic information" module of the blog Park. After checking the source code, we will find that this technology is used here.
Form:
Cookie: