CSRF and XSRF both stand for "Cross-site request forgery". It's also known as a "one click attack" or "session riding".
So how does a CSRF attack work? A CSRF attack happens when an attacker tricks a trusted user into accessing a website or clicking a URL that transmits malicious requests (without the user’s consent) to a targeted website. Here's a simple example: using a few social engineering tricks, an attacker could use the QQ chat software to find and send malicious links to victims targeted at their user's online banking website. If the victim logs into their online bank account and does not exit, then clicking on a malicious link sent from the attacker could allow the attacker to steal all of the user's bank account funds.
When under a CSRF attack, a single end-user with an administrator account can threaten the integrity of the entire web application.
The following diagram provides a simple overview of a CSRF attack
Figure 9.1 CSRF attack process.
As can be seen from the figure, to complete a CSRF attack, the victim must complete the following two steps:
-1. Log into trusted site A, and store a local Cookie. -2. Without going through existing site A, access the dangerous link to site B.
As a reader you may be asking: "If I do not meet the above two conditions, I will not be subjected to CSRF attacks." Yes this is true, however you cannot guarantee that the following does not occur:
- You cannot guarantee that when you are logged into a site, the site didn't launch any hidden tabs.
- You cannot guarantee that when you close your browser, your cookies will immediately expire and your last session will have ended.
- Trusted, high traffic websites will likely not have hidden vulnerabilities easily exploitable by CSRF based attacks.
Thus, it can be difficult for users to visit a website through a link and know that it will not carry out unknown operations in the form of a CSRF attack.
CSRF attacks work mostly because of the process through which users are authenticated. Although you can reasonably guarantee that a request originates from a user's browser, there is no guarantee that the user granted approval for the request.
You might be a little scared after reading the section above. But fear is a good thing. It will force you to educate yourself on how to prevent vulnerabilities like this from happening to you.
Preventative measures against CSRF attacks can be taken on both the server and client sides of a web application. However, CSRF attacks are most effectively thwarted on the server side.
There are many ways of preventing CSRF attacks on the server side. Most approaches stem from the following two aspects:
- Maintaining proper use of GET, POST and cookies.
- Including a pseudo-random number with non-GET requests.
In the previous chapter on REST, we saw how most web applications are based on GET and POST HTTP requests, and that cookies were included along with these requests. We generally design applications according to the following principles:
-
GET is commonly used to view information without altering any data.
-
POST is used in placing orders, changing the properties of a resource or performing other tasks.
I'm now going to use the Go language to illustrate how to restrict access to resources methods:
mux.Get("/user/:uid", getuser)
mux.Post("/user/:uid", modifyuser)
Since we've stipulated that modifications can only use POST, when a GET method is issued instead of a POST, we can refuse to respond to the request. According to the figure above, attacks utilizing GET as a CSRF exploit can be prevented. Is this enough to prevent all possible CSRF attacks? Of course not, because POSTs can also be forged.
We need to implement a second step, which is (in the case of non-GET requests) to increase the length of the pseudo-random number included with the request. This usually involves steps:
- For each user, generate a unique cookie token with a pseudo-random value. All forms must contain the same pseudo-random value. This proposal is the simplest one because in theory, an attacker cannot read third party cookies. Any form that an attacker may submit will fail the validation process without knowing what the random value is.
- Different forms contain different pseudo-random values, as we've introduced in section 4.4, "How to prevent multiple form submission". We can reuse the relevant code from that section to meet our needs:
Generating a random number token:
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
io.WriteString(h, "ganraomaxxxxxxxxx")
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, token)
Output token:
<input type="hidden" name="token" value="{{.}}">
Authentication token:
r.ParseForm()
token := r.Form.Get("token")
if token! = "" {
// Verification token of legitimacy
} Else {
// Error token does not exist
}
We can use the preceding code to secure our POSTs. You might be wondering, in accordance with our theory, whether there could be some way for a malicious third party to somehow figure out our secret token value? In fact, cracking it is basically impossible -successfully calculating the correct string value using brute force methods needs about 2 to the 11th time.
Cross-site request forgery, also known as CSRF, is a very dangerous web security threat. It is known in web security circles as a "sleeping giant" security issue; as you can tell, CSRF attacks have quite the reputation. This section not only introduced cross-site request forgery itself, but factors underlying this vulnerability. It concludes with some suggestions and methods for preventing such attacks. I hope this section will have inspired you, as a reader, to write better and more secure web applications.
- Directory
- Previous section: Security and encryption
- Next section: Filter inputs