CSRF cross-site request forgery attack

Cross-site Request Forf (CSRF) is an attack method to trick a user into performing an unintended action on a currently logged Web application.

In simple terms, a CSRF attack is the ability to forge a request on the victim’s behalf and send it to the target site without the user’s knowledge.

In contrast to XSS, XSS exploits the user’s trust in a given web site, and CSRF exploits the site’s trust in the user’s Web browser.

attacks

CSRF vulnerability is the use of website permission verification vulnerability to send requests without users' awareness, to achieve the purpose of camouflaged users.Copy the code

A typical CSRF attack has the following flow:

  • The victim logged on to a.com and retained the login credentials Cookie

  • The attacker lured the victim to visit b.com

  • B.com sends a request to a.com: a.com/act=xx, and the browser carries a Cookie from A.com by default

  • When a.com received the request, it verified it and confirmed that it was the victim’s credentials, mistaking it as a request sent by the victim himself

  • A.com enforced act= XXX on behalf of the victims

  • When the attack is complete, the attacker impersonates the victim without the victim’s knowledge and allows a.com to perform its own defined operation

Attackers use CSRF to implement the following attacks:

  • An attacker can trick the victim into performing any state change that the victim allows

    • Such as: update account details, complete shopping, logout and even login operations
  • Access to users’ private data

  • Cooperate with other vulnerability attacks

  • CSRF worms

GET the type

CSRF utilization of the GET type is very simple and requires only one HTTP request. It is typically utilized as follows:

<img src="http://bank.example/transfer? amount=10000&for=hacker" />
Copy the code

After the victim visits the page that contains the IMG, the browser automatically transfers to bank.example/ Transfer? Ac… Make an HTTP request. Bank.example will receive a cross-domain request containing the victim’s login information.

POST

This type of CSRF is typically exploited using an auto-submitted form, such as:

<form action="http://bank.example/transfer" method="POST">
  <input type="hidden" name="account" value="xiaoming" />
  <input type="hidden" name="amount" value="10000" />
  <input type="hidden" name="for" value="hacker" />
</form>
<script>
  document.forms[0].submit();
</script>
Copy the code

When you visit the page, the form is automatically submitted, simulating a POST operation. Post-type attacks are generally a little more stringent than GET, but still not complex. Any personal website, blog, website uploaded by hackers may be the source of attacks, back-end interface can not rely on the security of POST only above.

Link type

Link-type CSRFS are uncommon and require the user to click a link to trigger them, compared to the other two cases where the user opens the page and is caught. This type usually involves embedding malicious links in the pictures published in the forum, or inducing users to be lured in the form of advertisements. Attackers usually trick users into clicking with exaggerated words, such as:

<a href="http://test.com/csrf/transfer.php?amount=1000&for=hacker" taget="_blank"Word-wrap: break-word! Important; "> </a>Copy the code

Since the user logged in to the trusted website A and saved the login status, as long as the user actively accessed the above PHP page, the attack was successful.

Attack characteristics

  • Attacks are generally launched on third party sites, not the site being attacked. The attacked site cannot prevent the attack from happening

  • Instead of stealing data directly, the attack uses the login credentials of the victim’s targeted website to impersonate the victim to submit the action

  • The attacker does not obtain the victim’s login credentials during the whole process, but just uses them

  • Cross-site requests can be made in a variety of ways: image urls, hyperlinks, CORS, Form submissions, and more. Part of the request can be directly embedded in third-party forums, articles, difficult to track.

The result returned by the server cannot be parsed by the hacker due to the same origin policy of the browser. Therefore, the hacker gets nothing from the returned result, and all he can do is send a request to the server to execute the command described in the request, changing the value of the data directly on the server side, rather than stealing the data from the server. Therefore, we want to protect the services that can directly change the data, but for the services that read the data, CSRF protection is not required. For example, the transfer request in the banking system will directly change the amount of the account, which will be attacked by CSRF and need to be protected. However, the query amount is an operation to read the amount and does not change the data. CSRF attacks cannot parse the results returned by the server and do not require protection.

Defense strategy

CSRF is usually launched from third-party websites. Attacked websites cannot prevent attacks. They can only enhance their own protection against CSRF to improve security.

The above mentioned two characteristics of CSRF are described:

  • CSRF (usually) occurs in third party domain names

  • CSRF attackers cannot obtain information such as cookies, but only use

Develop protection strategies based on the characteristics of CSRF:

  • Block unknown outdomain access

    • Homology detection mechanism

      • Origin

      • Referer

    • Samesite Cookie

  • Submit by asking for additional information that is available only to the local domain

    • CSRF Token

    • Double Cookie authentication

  • Ensure that network requests are made by real users

    • User operation Restrictions

Homology detection mechanism

Since most CSRFS come from third-party sites, we simply forbid outlands (or untrusted domain names) from making requests to us. In HTTP, each part of a request carries two headers, which mark the source domain name:

  • Origin Header
  • Referrer 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.

origin

Use the Origin Header to determine the source domain name. In some CSRF-related requests, the request Header carries the Origin field. The field contains the requested domain name, excluding path and Query.

Origin: http://foo.example
Copy the code

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

But Origin doesn’t exist in two cases:

  • IE11 Same-origin policy: IE11 does not add the Origin header on cross-site CORS requests, and the Referrer header remains the unique identifier. The 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. For details, see MDN SAME-origin_policy #IE_Exceptions

  • 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.

Referrer

According to the HTTP protocol, there is a field in the HTTP header called referrer that records the source address of the HTTP request.

  • For Ajax requests, resource requests such as images and script files, the referrer is the address of the page that initiates the request.

  • For page jumps, referrer is the address of the previous page that opened the page history.

So we use the Origin part of the link in the Referrer to get the requested source domain name.

This method is not foolproof. The value of the referrer is provided by the browser. Although HTTP protocol has clear requirements, each browser may have different implementations of the referrer, which cannot guarantee that the browser itself is free from security vulnerabilities. The method of verifying the referrer values relies on the security of a third party (i.e. the browser), which in theory is not very secure. In some cases, attackers can hide or even modify the referrer of their own requests.

The new Referrer Policy specifies five Referrer policies:

  • No Referrer: No – the Referrer

  • No Referrer When Downgrade: no-referrer- When – downgraded

  • Origin Only: Origin

  • Origin When cross-orgin: origin-when-crossorigin

  • The Unsafe URL: Unsafe – URL

Use the Referer Policy

1. CSP response header, through the referrer instruction and five optional instruction values, to specify the referrer policy

Content-Security-Policy: referrer no-referrer|no-referrer-when-downgrade|origin|origin-when-cross-origin|unsafe-url;

Copy the code

2. Metadata tags can also specify Referrer policies

<! In any case, send only the source of the file as the reference address -->
<meta name="referrer" content="origin" />
Copy the code

3. The referrer attribute in the external chain tag or the referrerPolicy attribute on the < A >,

, ,

<a href="http://example.com" referrerpolicy="origin"></a>
Copy the code

Alternatively, you can set the REL attribute to noreferrer on ,

, or elements.

<a href="http://example.com" referrer="no-referrer|origin|unsafe-url">xxx</a>
Copy the code

This way only works for this one link. In addition, there are only three Referrer policies available for labels: none, host only, and all. In addition, this sets the policy for a single link to a higher priority than CSP and.

What happens when the Origin and Referrer headers do not exist? If neither Origin nor Referrer exists, it is recommended to block directly, especially if you are not using the random CSRF Token as a second check.

CSRF Token

Another feature of CSRF mentioned above is that attackers cannot directly steal the user’s information (cookies, headers, website content, etc.), but only use the information in cookies.

The CSRF attack succeeds because the server mistook the request sent by the attacker for the user’s own request. Then we can require all user requests to carry a Token that a CSRF attacker cannot obtain. By verifying whether the request carries the correct Token, the server can distinguish the normal request from the attack request and defend against CSRF attacks.

Realize the principle of

The CSRF Token defense policy consists of three steps:

1. Output the CSRF Token to the page

  • First of all, when the user opens the page, the server needs to generate a Token for the user, which encrypts the data through an encryption algorithm. Generally, the Token includes a combination of random strings and time stamps. Obviously, the Token can no longer be placed in the Cookie at the time of submission. Otherwise it will be used by attackers. Therefore, for the sake of security, it is better to keep the Token in the server’s Session, then use JS to traverse the whole DOM tree every time the page loads, and add the Token for 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.

For GET requests, the Token is appended to the request address so that the URL becomes http://url? Csrftoken = tokenvalue. For POST requests, the form ends with:

<input type="" hidden" " name="" csrftoken" " value="" tokenvalue" " />
Copy the code

This adds the Token to the request as a parameter.

3. The server verifies the Token

  • When a user obtains a token from the client and submits it to the server again, the server needs to determine the validity of the token by decrypting the token and comparing the encrypted string with the timestamp. If the encrypted string is consistent and the time has not expired, the token is valid.

  • This method is a bit safer than checking referer or Origin before. Tokens can be generated and placed in the Session, and then taken out of the Session on each request and compared with the tokens in the request. The trickier part of this approach, however, is how to add tokens to the request as parameters.

The following uses egg.js as an example to introduce some server-side verification logic for CSRF tokens.

CSRF = ctx.csrf; CSRF = ctx.csrf; CSRF = ctx.csrf;

<form method="POST" action="/upload? _csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data">
  title: <input name="title" /> file: <input name="file" type="file" />
  <button type="submit">upload</button>
</form>
Copy the code

The fields passing CSRF tokens can be changed in the configuration:

// config/config.default.js
module.exports = {
  security: {
    csrf: {
      queryName: '_csrf'.The default field for passing a CSRF token through query is _csrf
      bodyName: '_csrf'.// The default field for passing a CSRF token through body is _csrf,}}};Copy the code

To guard against BREACH attacks, CSRF tokens rendered synchronously to pages change with each request, and view plug-ins such as egg-view-Nunjucks inject forms automatically, unaware of the application developer.

In addition to CSRF verification of synchronous forms, there are also AJAX requests and the use of Session vs Cookie storage. For details, see CSRF protection against security threats.

Distributed check

Using sessions to store CSRF tokens can be stressful on large sites. The session for accessing a single server is the same. However, in today’s large websites, we usually have more than one server, maybe dozens or even hundreds of servers, and even multiple computer rooms may be in different provinces. HTTP requests initiated by users are usually routed to specific servers after load balancers such as Ngnix. By default, sessions are stored in the memory of a single server. Therefore, in a distributed environment, multiple HTTP requests sent by the same user may be sent to different servers successively. As a result, subsequent HTTP requests cannot get the Session data stored in the server of the previous HTTP requests. Therefore, the Session mechanism is invalid in a distributed environment. Therefore, CSRF tokens need to be stored in a public storage space such as Redis in a distributed cluster.

As Session storage is used, reading and verifying CSRF tokens will cause relatively large complexity and performance problems. Currently, many websites adopt Encrypted Token Pattern mode. The Token of this approach is a calculated result, not a randomly generated string. In this way, there is no need to read the stored Token during verification, but only need to calculate the Token again.

The Token value is usually generated by encryption using a UserID, timestamp, and random number. This ensures that the tokens of distributed services are consistent and that the tokens are not easy to crack. After the token is decrypted successfully, the server can access the resolved value, and the UserID and timestamp contained in the token will be used to verify the validity, comparing the UserID with the currently logged UserID, and comparing the timestamp with the current time.

User operation Restrictions

CSRF attacks in the process, the user is in unwittingly constructed network request, therefore add validation code can force users must interact with application, the server through the verification code to identify whether the user sends a request, because of a certain intensity verification code machine cannot identify, so dangerous website can’t forge a complete request.

  • Advantages: simple and effective, low cost

  • Cons: not user friendly, can’t add captcha to all operations

Defense Strategy Summary

A brief summary of the above defense strategy:

  • Automatic Defense Strategy for CSRF: Origin detection (Origin and Referrer verification)

  • The active defense policies of CSRF include CSRF Token authentication, double Cookie authentication, and Samesite Cookie

  • Keep the page idempotent, and the backend interface does not do user operations in the GET page

Why does token end up storing a copy in a cookie?

Because if you do not save, the next time you open this page, you will have to log in again if you cannot find the token

Why are cookies safe?

Because different domain names cannot obtain cookies, third parties cannot obtain cookies to send requestsCopy the code