Nowadays, most of us shop online. But what many people don’t know is that many e-commerce sites have security vulnerabilities. Dark clouds have been notified, many domestic companies have CSRF vulnerability in their websites. If a website has this kind of security flaw, then we are very likely to be in the process of shopping, cyber hackers charge credit cards. Do you have a sudden “chill” feeling?
First, we need to figure out what CSRF is. It stands for cross-site request forgery, which is a malicious exploitation of a website. To put it simply, a malicious website acts as us on a website you log in to without our knowledge — sending messages, buying things, or even transferring money to……
This attack pattern sounds a bit like cross-site scripting (XSS), but CSRF is very different from XSS and attacks in almost the opposite way. XSS exploits trusted users within the site, while CSRF exploits trusted web sites by masquerading requests from trusted users. CSRF attacks tend to be rare compared to XSS attacks, so resources to defend against them are scarce. However, this “trusted” attack mode is harder to defend against and is considered more dangerous than XSS.
How does this process work? Let’s look at a simple and vivid example.
Bank website A, which uses GET request to complete bank transfer operation, 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
What is likely to happen? You log on to bank website A, then visit dangerous website B, and suddenly find that your bank account is missing $10,000……
Why is that? The reason is that before visiting the dangerous website B, you have logged in to the bank website A, and the third party resources in B are requested in the form of GET. So your browser will take the Cookie of your bank website A and issue A GET request to GET resources
“Http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,
As a result, the bank’s website server received the request, decided that it was a reasonable transfer operation, and immediately transferred……
Real bank sites would not be so unguarded, but even using POST instead of GET would only make dangerous sites work a little harder. Dangerous web sites can still try to steal customer money by embedding Javascript, so it’s not uncommon to hear of customer money being stolen from time to time.
I believe that many of us will break into a cold sweat when we learn about this, and will we be able to enjoy the pleasure of online shopping during 618? Isn’t there any way to prevent it?
Of course there is.
In the industry, there are three main defenses against CSRF attacks: verifying HTTP Referer fields; Add token to request address and verify; Customize and validate properties in HTTP headers. These three strategies are described in detail below.
Validate the HTTP Referer field
According to the HTTP protocol, there is a field in the HTTP header called Referer that records the source address of the HTTP request. Typically, a request to access a security-restricted page comes from the same website, such as the need to access bank.example/withdraw? Ac… , the user must log in to bank.Example and trigger the transfer event by clicking the button on the page. In this case, the Referer value of the transfer request will be the URL of the page where the transfer button is located, usually starting with the bank.example domain name. If a hacker wants to carry out A CSRF attack on a bank’s website, he can only construct a request on his own website. When a user sends a request to the bank through the hacker’s website, the Referer of the request is directed to the hacker’s own website. Therefore, to defend against CSRF attacks, bank websites only need to verify the Referer value of each transfer request. If the domain name starts with bank.example, it indicates that the request is from the bank website itself and is legitimate. If the Referer is any other site, it could be a CSRF attack by a hacker to reject the request.
The obvious benefit of this approach is that it is so simple that the average developer of a site doesn’t have to worry about CSRF vulnerabilities, just adding a single interceptor to all security-sensitive requests at the end to check the Referer value. Especially for the current existing system, there is no need to change any existing code and logic of the current system, no risk, very convenient.
However, this approach is not foolproof. The value of the Referer is provided by the browser. Although there are clear requirements on the HTTP protocol, the specific implementation of the Referer by each browser may be different, and there is no guarantee that the browser itself is free of security vulnerabilities. The method of verifying the Referer value relies on the security of a third party (i.e. the browser), which in theory is not secure. In fact, for some browsers, such as IE6 or FF2, there are already ways to tamper with the Referer value. If the bank.example site supports Internet Explorer 6, the hacker could have set the Referer value of the user’s browser to an address that starts with the bank.example domain name, so that it can be verified and CSRF attacks can be carried out.
Even with the latest browsers, hackers can’t tamper with the Referer value, which is problematic. Because Referer records the source of the user’s access, some users feel that this will violate their privacy, especially some organizations concerned that the Referer value will leak some information from their internal network to the external network. Therefore, users themselves can set the browser to no longer provide Referer when sending requests. When they visit the bank’s website normally, the website will consider the request as a CSRF attack because it does not have the Referer value and deny the access to legitimate users.
Add token to request address and validate
The reason why CSRF attack can be successful is that the hacker can completely forge the user’s request, and all the user authentication information in the request is in the cookie, so the hacker can directly use the user’s own cookie to pass the security authentication without knowing the authentication information. The key to defending against CSRF is to put information in the request that a hacker cannot forge and that does not exist in a cookie. A randomly generated token can be added to the HTTP request as a parameter, and an interceptor can be established on the server side to verify the token. If there is no token in the request or the token content is incorrect, the request may be rejected as a CSRF attack.
This is more secure than checking the Referer. Tokens can be generated after the user logs in and placed in the session, and then taken out of the session on each request and compared with the tokens in the request. The difficulty with this approach, however, is how to add tokens to the request as parameters. For GET requests, the token is appended to the request address so that the URL becomes http://url? Csrftoken = tokenvalue. For POST requests, add at the end of the form to add the token as a parameter to the request. However, in a website, there are so many places to accept requests that adding a token to each request is cumbersome and easy to miss. The usual method is to traverse the dom tree with javascript every time the page loads. Add the token after all a and FORM tags in the DOM. This solves most requests, but for HTML code that is generated dynamically after the page loads, this approach does not work and requires the programmer to manually add tokens at coding time.
Another disadvantage of this approach is that it is difficult to guarantee the security of tokens themselves. Especially in some forums and other websites that support users to publish their own content, hackers can publish their own personal website address. Since the system also adds a token to the address, the hacker can get the token on his own website and launch a CSRF attack right away. In order to avoid this, the system can add a judgment when adding the token, if the link is linked to their own site, add the token later, if it is to the Internet, do not add. However, even if the CSRFtoken is not attached to the request as a parameter, a hacker’s site can also obtain the token value via the Referer to launch a CSRF attack. This is why some users prefer to turn off the browser Referer manually.
Customize and validate properties in HTTP headers
This method also uses the token and validates it. Unlike the previous method, instead of placing the token in the HTTP request as a parameter, it places it in a custom attribute in the HTTP header. With the XMLHttpRequest class, you can add the CSRFToken HTTP header attribute and put the token value into all of the class requests at once. This eliminates the inconvenience of adding the token to the request in the previous method, and the XMLHttpRequest address is not logged in the browser’s address bar, and the token is not leaked to other sites through the Referer.
However, this approach has significant limitations. XMLHttpRequest is usually used for asynchronous partial page refresh in Ajax methods. Not all requests are suitable to be initiated with this class, and the page obtained through this class cannot be recorded by the browser, thus making it inconvenient for users to move forward, backward, refresh, and save. In addition, for legacy systems without CSRF protection, this approach to protection requires that all requests be converted to XMLHttpRequest requests, which is almost an entire web site rewrite, an unacceptable cost.
Java code examples
The following sections illustrate each of the three methods in code, using Java as an example. Regardless of the method used, an interceptor on the server side is essential, which checks the incoming request for compliance and then decides whether to continue or discard the request based on the result. In Java, interceptors are implemented by filters. We can write a Filter and configure it in web.xml to intercept requests for access to all resources that need CSRF protection.
The Referer validation code for the request in the filter is as follows
Listing 1. Validate the Referer in the Filter
String Referer = request.getheader ()"Referer"); // Referer does not start with bank.exampleif((referer! = null) && (referer. The trim (). The startsWith (" bank. Example "))) {chain. DoFilter (request, response); }else{request. GetRequestDispatcher (" error. JSP "). The forward (request, response); }Copy the code
The above code gets the Referer value, evaluates it, and if it is non-empty and starts with bank.example, continues the request, otherwise it could be a CSRF attack and go to the error.jsp page.
To further verify the token value in the request, the code is as follows
Listing 2. Validate the token in the request in filter
HttpServletRequest req = (HttpServletRequest)request; HttpSession s = req.getSession(); // Get the csrfToken attribute from session. String sToken = (String) s.get_attribute (" csrftoken ");if(sToken == null){// Generate a new token into the session sToken = generateToken(); S.s etAttribute (" csrftoken, "sToken); chain.doFilter(request, response); }else{// Get csrfToken from HTTP header String xhrToken = req.getheader (" csrftoken "); PToken = req.getParameter(" csrfToken ");if(sToken ! = null && xhrToken ! = null && sToken.equals(xhrToken)){ chain.doFilter(request, response); }else if(sToken ! = null && pToken ! = null && sToken.equals(pToken)){ chain.doFilter(request, response); }else{request. GetRequestDispatcher (" error. JSP "). The forward (request, response); }}Copy the code
First, check whether there is a CSRftoken in the session. If there is no cSRFtoken in the session, it is considered as the first access and the session is newly established. In this case, a new token is generated, placed in the session, and the request continues to be executed. If there is a cSRFToken in the session, then the user has established an active session with the server. If there is a cSRFToken in the session, then the user has established an active session with the server. We try to get the CSRFToken parameter from the request and the cSRFToken custom attribute from the HTTP header respectively and compare it with the value in the session. As long as there is a valid token in one place, the request is judged to be valid and can continue to execute, otherwise we will go to the error page. There are many ways to generate tokens, and any random algorithm can be used. Java’s UUID class is also a good choice.
In addition to using filter to verify the token value on the server side, we also need to append the token to each request on the client side, which uses JS to append cSRFToken code to the link and form request address in HTML, where token has been defined as a global variable. The value can be obtained from session.
Listing 3. Attach tokens to requests on the client side
function appendToken(){
updateForms();
updateTags();
}
function updateForms() {/ / in the page, all the form elements of var forms = document. The getElementsByTagName ('form');
for(i=0; i<forms.length; i++) { var url = forms[i].action; // If the action value of this form is empty, no csrFToken is attachedif(url == null || url == "" ) continue; Var e = document.createElement(var e = document.createElement("input");
e.name = "csrftoken";
e.value = token;
e.type="hidden"; forms[i].appendChild(e); }}function updateTags() {
var all = document.getElementsByTagName('a'); var len = all.length; // Iterate over all a elementsfor(var i=0; i<len; i++) {
var e = all[i];
updateTag(e, 'href', token); }}function updateTag(element, attr, token) {
var location = element.getAttribute(attr);
if(location ! = null && location ! =' ' ' ' ) {
var fragmentIndex = location.indexOf(The '#');
var fragment = null;
if(fragmentIndex ! Fragment = location. subString (fragmentIndex); // Fragment = location.substring(fragmentIndex); location = location.substring(0,fragmentIndex); } var index = location.indexOf('? ');
if(index ! = -1) {// the url already contains other parameters location = location +'&csrftoken=' + token;
} else{// there are no other parameters in the url location = location +'? csrftoken=' + token;
}
if(fragment != null){
location += fragment;
}
element.setAttribute(attr, location);
}
}Copy the code
In the client HTML, there are two main places to add tokens, one is the form and the other is the link A. This code first iterates through all the forms and adds a hidden field at the end of the form to put the CSRFToken into it. The code then iterates through all the link tag A, adding the cSRFToken argument to its href attribute. Note that in the case of A.ref, the attribute may already have parameters, or an anchor tag. Therefore, it is necessary to discuss the case by case and add cSRFToken in different formats.
If your site uses XMLHttpRequest, you also need to customize the cSRFToken attribute in the HTTP header. Using dojo. XHR, add the following code to the XMLHttpRequest custom attribute:
Listing 4. Custom attributes in the HTTP header
var plainXhr = dojo.xhr; // Override the dojo.xhr method dojo.xhr =function(method, args, hasBody) {/ / make sure the header object exists the args. The headers = args. The header | | {}; tokenValue ='<%=request.getSession(false).getAttribute("csrftoken")%>';
var token = dojo.getObject("tokenValue"); // Put the csrFToken attribute in the header."csrftoken"] = (token) ? token : "";
return plainXhr(method,args,hasBody);
};Copy the code
This overwrites the dojo. XHR method by first ensuring that dojo. XHR has HTTP headers, then adding the CSRFToken field to args.headers and taking the token value out of the session and putting it in the field.
CSRF defense method selection
As can be seen from the above discussion, there are some restraint methods to deal with CSRF attacks in the industry at present, but each method has advantages and disadvantages, and none of them is perfect. How to choose the right method is very important. If the site is an existing system and wants to obtain a certain degree of CSRF protection in the shortest time, then verifying the Referer method is the most convenient. In order to increase security, you can choose not to support the lower version of the browser, after all, for the moment, The Referer value of older browsers like IE7+ and FF3+ cannot be tampered with.
If the system must support IE6, you still need high security. In most cases, XmlHttpRequest is not appropriate. Tokens can only be used as parameters in requests. If your system does not support users Posting information themselves, then this level of protection is sufficient. It’s still hard to prevent your tokens from being stolen and attacked by hackers. In this case, you need to carefully plan the various services provided by your website, identify the parts that allow users to publish their own information, separate them from other services, and use different tokens to protect them, so that you can effectively prevent hackers from attacking your key services and minimize the harm. After all, deleting a post from someone else’s account is less serious than simply transferring a large sum of money from someone else’s account.
If you are developing an entirely new system, the options for resisting CSRF are much greater. I recommend that you use XMLHttpRequest to access important services as much as possible, which makes it much easier to add tokens. Also try to avoid using complex logic in JS code to construct regular synchronous requests to access CSRF protected resources such as window.location and document.createElement(” a “). This can also reduce unnecessary hassle when attaching tokens.
Finally, keep in mind that CSRF is not the only means of attack for hackers. No matter how well protected you are against CSRF, if you have other security vulnerabilities, such as cross-site scripting against XSS, then hackers can bypass your security and carry out various attacks, including CSRF, and your defenses will be useless. Only when we fully pay attention to CSRF and choose the most appropriate strategy according to the actual situation of the system, can we minimize the harm of CSRF.
Click to follow, the first time to learn about Huawei cloud fresh technology ~