CSRF is introduced

CSRF, short for Cross Site Request Forgery, is an attack that hijacks a trusted user to send an unexpected Request to the server.

Under normal circumstances, CSRF attack means that the attacker uses the victim’s Cookie to cheat the trust of the server, and sends forged requests to the attacked server in the victim’s name without the victim’s knowledge, so as to perform operations under permission protection without authorization.

Example of CSRF attack

There is a website where users can read articles, log in and post comments.

If the user is logged in and opens a page like this,

<! DOCTYPEhtml>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>CSRF attacks</title>
    <meta content="Width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = 0" name="viewport" />
</head>

<body style="display: none;">
    <form target="myIframe" id="csrf" action="https://www.kkkk1000.com/csrf/data/post_comment.php" method="POST">
        <input type="text" name="content" value="CSRF attacks" />
    </form>

    <! -- iframe is used to prevent page skipping -->
    <iframe id="myIframe" name="myIframe"></iframe>

    <script>
        var form = document.querySelector('#csrf');
        form.submit();
    </script>
</body>

</html>
Copy the code

A CSRF attack is completed by automatically Posting a comment to the article. Of course, if you put this page on the server and make a link, users click on the link, you can also complete the attack.

As can be seen from the figure, the pages on the right and left are under different sites. When the user opens the blank page on the right, he secretly submits a comment, and when he refreshes the page on the left, he actually sees the comment he just submitted.

Let’s see how the attack worked.

First we need to know a little bit about cookies.

An HTTP Cookie (also known as a Web Cookie or browser Cookie) is a small piece of data that a server sends to a user’s browser and keeps locally. It is carried and sent to the server the next time the browser makes a request to the same server. Typically, it is used to tell the server whether two requests are from the same browser, such as to keep the user logged in. Cookies make it possible to record stable state information over stateless HTTP protocols.

Okay, let’s move on.

After the user logs in to the website, the website server will put a credential in the Cookie, which is used by the back end to verify the user’s identity. When a comment is sent, the request to submit a comment will carry this credential, and the backend will identify the user by judging this credential.

When logging in, set cookies:

When submitting a comment, carry a Cookie:

Let’s take a look at the contents of the page that launched the attack.

<body style="display: none;">
    <form target="myIframe" id="csrf" action="https://www.kkkk1000.com/csrf/data/post_comment.php" method="POST">
        <input type="text" name="content" value="CSRF attacks" />
    </form>

    <! -- iframe is used to prevent page skipping -->
    <iframe id="myIframe" name="myIframe"></iframe>

    <script>
        var form = document.querySelector('#csrf');
        form.submit();
    </script>
</body>
Copy the code

What this code means is that when the user clicks on the link, it will automatically submit the form that is used to submit the comment, and the parameters required to submit the comment request are already prepared in the form. If the user has logged in to the website, the user’s credentials stored in the Cookie, Is sent to the server with the request. So the server side will assume that this is the user submitting a comment.

CSRF characteristics

  • Attacks are generally launched on third party sites, not the site being attacked.
  • The attack is to use the victim’s login credentials on the attacked website, pretending to be the victim to submit operations, just “impersonation”, rather than directly stealing data.
  • The attacker predicts all the parameters of the interface of the attacked site and successfully forges the request.

defense

SameSite properties

The SameSite property of cookies is used to limit third-party cookies, thereby reducing security risks, and can be used to prevent CSRF attacks and user tracking.

It can set three values.

  • Strict
  • Lax
  • None

Strict

Strict is the strictest and completely forbids third-party cookies. Cookies are never sent across sites under any circumstances. In other words, cookies are carried only if the URL of the current web page matches the target of the request.

Set-Cookie: CookieName=CookieValue; SameSite=Strict;
Copy the code

This rule is too strict and can lead to a very bad user experience. For example, if there is a GitHub link on the current webpage, users will not have GitHub cookies when they click the jump, and the jump will always be unlogged.

Lax

The Lax rule is slightly relaxed, and third-party cookies are also not sent in most cases, except for Get requests that navigate to the target url.

Set-Cookie: CookieName=CookieValue; SameSite=Lax;
Copy the code

Chrome plans to make Lax the default. At this point, the site can choose to explicitly turn off the SameSite property and set it to None. However, the Secure attribute must be set at the same time (cookies can only be sent through HTTPS). Otherwise, cookies are invalid.

The following Settings are invalid:

Set-Cookie: widget_session=abc123; SameSite=None
Copy the code

The following Settings are valid:

Set-Cookie: widget_session=abc123; SameSite=None; Secure
Copy the code

To use the SameSite property, the user’s browser supports the SameSite property. You can use caniuse to check the browser’s support for the SameSite property.

Homologous detection

In HTTP, each asynchronous request carries two headers, which mark the domain name of the source:

  • Origin Header
  • Referer Header

These two headers are carried automatically in most cases when the browser makes a request, and the content cannot be customized by the front end. The server can determine the source domain of the request by resolving the domain names in the two headers.

By validating this field in the request, we can tell if the request was made from this site. We can avoid CSRF attacks by rejecting requests from other sites.

Verify the Origin

If Origin exists, just use the fields in Origin to identify the source domain name.

But Origin doesn’t exist in two cases:

  • 1. Internet Explorer 11 Origin policy: Internet Explorer 11 will not add the Origin header to cross-site CORS requests, and the Referer header will remain the unique identifier. The most fundamental reason is that the definition of same-origin in Internet Explorer 11 is different from that in other browsers. There are two major differences, please refer to MDN SAME-origin_policy #IE_Exceptions

  • 2, 302 redirects: After 302 redirects Origin is not included in redirected requests because Origin may be considered sensitive information from other sources. In the case of 302 redirects, the URL is directed to the new server, so the browser does not want to leak Origin to the new server.

Verify the Referer

Referer, if it exists, can also be used to confirm the source address of the HTTP request.

It should be noted that Referer is not or cannot be trusted in the following situations:

  • 1. Use Internet Explorer 6 or 7window.location.href=urlWhen the interface jumps, the Referer will be lost.
  • 2. Use Internet Explorer 6 or 7window.open, Referer will also be missing.
  • 3. When the HTTPS page is switched to the HTTP page, the Referer of all browsers is lost.
  • 4. When clicking Flash to reach another website, the Referer’s situation is messy and not credible.

In general, same-origin detection is a relatively simple defense method that can prevent the vast majority of CSRF attacks, but it is not foolproof. For sites with high security requirements or a large amount of user input, we need to do additional protection measures for key interfaces.

Verification code

There are many types of captcha, such as graphic captcha, captcha based on knowledge differences between human and machine, and behavioral captcha.

CSRF attacks are often successful forgeries of requests without the user’s knowledge. Captcha forces the user to interact with the application to complete the final request, and because CSRF attacks cannot obtain captcha, it is generally a good deterrent against CSRF attacks. But captcha is not a panacea, because for user experience, you can’t add captcha to every operation on a website. Therefore, captchas can only be used as an adjunct to CSRF defense, not as a primary solution.

Adding Token Authentication

The reason why CSRF attack can be successful is that the attacker can completely forge the user’s request, and all the user authentication information in the request is in the Cookie, so the attacker 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 an attacker 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.

Steps for adding Token authentication:

When the user opens the page, the front-end initiates a request and the server returns a Token, which encrypts the data through an encryption algorithm. Generally, tokens include random string and timestamp combinations. The Token is stored in the Session of the server. Then, when the page is loaded, JS is used to traverse the whole DOM tree, and Token is added to the A and form tags of all addresses in the DOM. Other requests are manually added to the Token parameter during encoding.

For GET requests, the Token is appended to the request address so that the URL becomes http://url? Token = tokenvalue. For POST requests from the form tag, add the following at the end of the form:

<input type="Hidden" name="Token" value=Tokenvalue "/">
Copy the code

In short, the front-end sends a request to add the Token in the form of parameters in the request.

3. The server verifies whether the Token is correct. The server needs to determine the validity of the Token by decrypting the Token and comparing the encrypted string with the timestamp. Then the Token is valid.

conclusion

The essence of CSRF’s success is that all parameters of important operations can be guessed by the attacker. So just prevent the attacker from successfully constructing a bogus request, you can stop the attack!

case

CSRF vulnerability on the Hilton website

Sina Weibo CSRF vulnerability

CSRF vulnerability in WordPress

reference

HTTP cookies

The SameSite property of the Cookie

Principle of CSRF vulnerability

CSRF defense mechanism in front – end separation architecture

Front-end Security Series 2: How do I Prevent CSRF Attacks?

CSRF attack response