“Full stack cultivation” series

  1. [Full Stack Cultivation] OAuth2 Cultivation Treasure Book

CORS and CSRF are too easy to confuse, as this article will make clear.

I. Differences between CORS and CSRF

Take a look at the picture below:

The two concepts are completely different, and we also see XSS quite often, which is introduced here:

  1. CORS: Cross Origin Resourse-sharing Cross-site resource Sharing

  2. CSRF: Cross-site Request Forgery

  3. XSS: Cross Site Scrit cross-site scripting attack (called XSS in the security world to distinguish it from CSS)

Second, the CORS

1. The concept

Cross-source Resource Sharing (CORS), also known as cross-domain resource Sharing, is a specification of browser technology that provides a way for Web services to sandbox scripts from different domains, circumventing the browser’s same-origin policy, and is a modern version of the JSONP pattern. Unlike JSONP, CORS supports other HTTP requests in addition to the GET request method. CORS allows web designers to use generic XMLHttpRequest, which has better error handling than JSONP. JSONP, on the other hand, can run on older browsers that do not support CORS. Modern browsers all support CORS.

— Wikipedia

Core knowledge: CORS is a W3C standard that allows browsers to make XMLHttpRequest requests across source servers, overcoming the limitation that AJAX can only be used in the same source.

Therefore, the key to CORS communication is the server. As long as the server implements the CORS interface, it can communicate across sources, that is, to solve cross-domain problems.

2. CORS request type

Browsers classify CORS requests into two categories: Simple request and not-so-simple Request.

Simple requests generally include the following two situations:

situation describe
Request method Request method:HEADGETPOST;
HTTP headers The HTTP header does not exceed the following fields:Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type: Is limited to three valuesapplication/x-www-form-urlencoded,multipart/form-data,text/plain

Any request that does not meet both conditions is a non-simple request.

3. CORS process for simple requests

When the browser discovers that our AJAX request is a simple one, it automatically adds an Origin field to the header information.

The Origin field indicates the source of the request (including the protocol, domain name, and port number). The server determines whether to approve the request based on this value.

When Origin specifies a source outside the permitted scope, the server returns a normal HTTP response, but the browser finds the Access-Control-Allow-Origin field in the response header and throws an exception.

When Origin is within the license range, the server returns several additional header fields in the response header:

In addition to the header in the figure above, there are generally three related headers:

  1. Access-Control-Allow-Origin

This field is required. The domain name that represents the license scope, usually with one of two values: the value of the Origin field at request time or the * (asterisk) for any domain name.

  1. Access-Control-Allow-Credentials

This field is optional. Boolean value indicating whether cookies are allowed to be sent in CORS requests. If cookies are not carried, you do not need to set this field.

When set to true, cookies are included in the request and sent to the server. You also need to enable the withCredentials attribute in the AJAX request, otherwise the browser will not send cookies.

let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
Copy the code

Note: If the front – end access-Control-allow-credentials are set to true to carry cookies to initiate requests, the server access-Control-allow-Origin cannot be set to *.

  1. Access-Control-Expose-Headers

This field is optional. You can set the fields to be obtained. Because by default, the getResponseHeader() method of the XMLHttpRequest object takes only the following six basic fields on a CORS request:

Cache-control, Content-language, Content-Type, Expires, Last-Modified, Pragma.

4. CORS process for non-simple requests

For example, the request method is PUT/DELETE or Content-Type:application/ JSON.

When CORS requests are not simple requests, a “pre-check” request (OPTIONS method) is added before formal communication to ask the server whether the requested domain name is on the permissive list and which headers to use.

The AJAX request is officially initiated only after the precheck request passes; otherwise, an error is reported.

4.1 Precheck request

OPTIONS /cors HTTP / 1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
User-Agent: Mozilla/5.0...
...
Copy the code

The Precheck request information contains two special fields:

  1. Access-Control-Request-Method

This field is required to list which HTTP methods are used by the browser for CORS requests, in this example PUT.

  1. Access-Control-Request-Headers

Specifies the additional Header field that the browser CORS requests to send, in this example x-custom-header.

4.2 Pre-check response

HTTP / 1.1 200 OK
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Connection: Keep-Alive
...
Copy the code

When the precheck request is approved, access-Control-allow-origin is returned in the precheck response header, where access-Control-allow-origin indicates the permitted range and can also be *.

When a precheck request is rejected, the access-Control-allow-beginning message is not returned in the precheck response header and an error message is printed on the console.

Third, CSRF

1. The concept

Cross-site request forgery Cross-site Request Forgery, also known as one-click attack or session riding, usually abbreviated as CSRF or XSRF, Is a method of hijacking a user to perform unintended actions on a currently logged Web application. In contrast to cross-site scripting (XSS), which exploits the user’s trust in a given site, CSRF exploits the site’s trust in the user’s Web browser.

— Wikipedia

Core knowledge: Request forgery across sites.

Simple: An attacker steals your identity and sends malicious requests on your behalf.

Common scenarios: send emails in your name, send messages, steal your account, even buy goods, virtual currency transfer and so on.

Impact: personal privacy and property security.

2. CSRF attack process

The CSRF attack flow is described above, where the victim completes two steps:

  1. Log in to trusted website A and generate and save cookies locally;
  2. Visit the virus site B without logging out of A;

If the preceding two steps are not completed, CSRF attacks will not occur.

3. The server defends against CSRF attacks

There are many ways in which the server can defend itself, and the idea is similar, by adding pseudorandom numbers to the client page.

3.1 Cookie Hashing (All forms contain the same pseudorandom number)

The simplest and most effective way, because the attacker theoretically cannot obtain the Cookie of the third party, the form data forgery fails. Take PHP code as an example:


      
    // Construct encrypted Cookie information
    $value = "LeoDefenseSCRF";
    setcookie("cookie".$value, time()+3600);
? >
Copy the code

Add a Hash value to the form to verify that the request was actually sent by the user.


      
    $hash = md5($_COOKIE['cookie']);
? >
<form method="POST" action="transfer.php">
  <input type="text" name="toBankId">
  <input type="text" name="money">
  <input type="hidden" name="hash" value="<? =$hash; ? >">
  <input type="submit" name="submit" value="Submit">
</form>
Copy the code

Then Hash value authentication is performed on the server side.


      
    if(isset($_POST['check']) {$hash = md5($_COOKIE['cookie']);if($_POST['check'] = =$hash) {
            doJob();
        } else{/ /...}}else{/ /...
    }
? >
Copy the code

In my opinion, this method has prevented 99% of CSRF attacks, and 1%…. Since users’ cookies are easily stolen due to XSS vulnerabilities on the site, this is another 1%.

Most attackers will give up when they see a Hash value, except for some, so this is not the best method if 100% elimination is required.

3.2 authentication code

The idea is: every time the user submits, the user needs to fill in a random string on the picture in the form. This scheme can completely solve the CSRF, but the usability is poor, and the use of captchas image involves the MHTML Bug, which may be affected in some versions of Microsoft IE.

3.3 One-time Tokens(Different forms Contain a Different pseudo-random Value)

Note “parallel session compatibility”. If a user has two different forms open on the same site at the same time, CSRF protection should not affect his submission of any form. Consider what would happen if the site generated a pseudo-random value to override the previous pseudo-random value each time a form was loaded: the user can only successfully submit the form he opened last, because all the other forms contain illegal pseudo-random values. Care must be taken to ensure that CSRF protection does not affect tabbed browsing or browsing a site with multiple browser Windows.

The PHP implementation is as follows:

  1. First,TokenToken generation function (gen_token()) andSessionToken generation function (gen_stoken()) :

      
    function gen_token() {
        $token = md5(uniqid(rand(), true));
        return $token; }function gen_stoken() {$pToken = "";if($_SESSION[STOKEN_NAME]  == $pToken) {$_SESSION[STOKEN_NAME] = gen_token (); }else{}}? >
Copy the code
  1. The WEB form generates a function that hides the input field:

      
    function gen_input() {
        gen_stoken();
        echo "<input type=\"hidden\" name=\"" . FTOKEN_NAME . "\" value = \ "" . $_SESSION[STOKEN_NAME] . "\"> "; }? >
Copy the code
  1. WEB form structure:

      
    session_start();
    include("functions.php");
? >
<form method="POST" action="transfer.php">
    <input type="text" name="toBankId">
    <input type="text" name="money">
    <? gen_input(); ? >
    <input type="submit" name="submit" value="Submit">
</FORM>
Copy the code
  1. The server verifies the token

This step is very simple and I won’t go into details.

Four, XSS

Note: this article introduces knowledge of XSS, specific details can be read FEWY wrote the cross-site scripting attacks – XSS segmentfault.com/a/119000002…

1. The concept

Cross-site scripting (commonly referred to as XSS) is a type of web application security vulnerability attack that is a form of code injection. It allows malicious users to inject code into web pages that can affect other users when they view them. Such attacks often involve HTML and client-side scripting languages.

— Wikipedia

An XSS attack is an attack in which an attacker injects malicious scripts into a web page. When a user browses a web page, the malicious scripts are executed to control the user’s browser behavior.

Common XSS hazards include:

  • Steal user cookies, obtain user privacy, steal user accounts.
  • Hijacking user (browser) sessions to perform arbitrary actions, such as making illegal money transfers, forcing logs, sending e-mails, etc.
  • Forced pop-up AD pages, brush traffic, spread cross-site scripting worms, web page hanging horse, etc.
  • Combined with other vulnerabilities, such as the CSRF vulnerability, to carry out further attacks.

2. XSS classification

3. XSS defenses

3.1 Method 1: X-xSS-protection provided by Browsers

Today’s major browsers (Internet Explorer, Chrome, and Safari) have an HTTP X-XSS-protection response header that stops the browser from loading the page when a cross-site scripting attack (XSS) is detected.

The x-XSS-protection response header has the following four values:

  • X-XSS-Protection: 0

Disable XSS filtering.

  • X-XSS-Protection: 1

Enable XSS filtering (usually the default for browsers). If a cross-site scripting attack is detected, the browser wipes out the page (removing unsafe portions).

  • X-XSS-Protection: 1; mode=block

Enable XSS filtering. If an attack is detected, the browser will not clear the page, but block the page from loading.

  • X-XSS-Protection: 1; report=<reporting-uri>

Enable XSS filtering. If a cross-site scripting attack is detected, the browser clears the page and sends a violation report using the functionality of the CSP report-URI directive.

Note:

This does not completely protect against reflective XSS, and not all browsers support X-XSS-protection, causing compatibility issues.

It is only somewhat defenseless against reflective XSS and works by simply checking the correlation between urls and elements in the DOM.

3.2 Method 2: Escape

The common special characters are escaped to prevent attackers from using constructed special characters to inject scripts. The data entered by the user needs to be escaped on both the client and server sides.

Common special characters that need to be escaped are <, >, &, “, ‘.

Escape method:

function escapeHTML(str) {
    if(! str)return ' ';
    str = str.replace(/&/g."&amp;"); str = str.. replace(/</g."&lt;"); str = str.. replace(/>/g."&gt;"); str = str.. replace(/"/g."&quot;"); str = str.. replace(/'/g."& # 39;");
    return str;
};
Copy the code

3.3 Method 3: Filtering

This is common in rich text content, which cannot be escaped directly because it needs to preserve HTML, but can be protected against XSS attacks by using whitelists to allow specific HTML tags and attributes.

3.4 Approach 4: Content Security Policy (CSP)

Content Security Policy (CSP) is essentially a whitelist system. Developers clearly tell clients which external resources can be loaded and executed, greatly enhancing the Security of web pages.

There are two ways to enable CSP.

  1. Through HTTP headersContent-Security-PolicyThe field of:
Content-Security-Policy: script-src 'self'; 
                         object-src 'none';
                         style-src cdn.example.org third-party.org; 
                         child-src https:
Copy the code
  1. web-based<meta>The label
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
Copy the code

In the code above, the CSP does the following configuration:

  • Script: Trust only the current domain name
  • <object>Tags: Do not trust any URLS, that is, do not load any resources
  • Style sheets: Trust onlycdn.example.org and third-party.org
  • Page content, as<frame>,<iframe>: HTTPS must be used
  • Other resources: No restrictions
  • When enabled, external resources that do not comply with CSP are blocked from loading.

Refer to the article

  1. Detailed explanation of Cross-domain Resource Sharing CORS
  2. CSRF & CORS
  3. Discussion on CSRF Attack Mode
  4. Cross-site Scripting Attacks — XSS