1. Overview of CSRF principles and defense schemes

A principle.

  1. Add, delete, and modify interface parameter values are regular and can be maliciously constructed

  2. The malicious structure of the add, delete and change interface to corresponding specific users, so that specific users click

  3. Specific users use their own authentication information to initiate requests to the interface, which may add dangerous information (such as administrator account), modify sensitive information (such as refund amount), and delete key information (such as deleting bad reviews).

Ii. Overview of defense plan

  1. Parameter cannot be guessed. Random token parameter is added to the parameter when the request is initiated

  2. The token parameter is compared with the token parameter stored in cookie,session, and TAIR in the background. If the token parameter does not match or does not exist, the verification fails

  3. Hackers cannot obtain random token values of specific users, so CSRF is not compromised

2 ALI repair scheme

one.Confirm the Application Type

CSRF needs to be configured if services such as adding, deleting, and modifying data or files are provided for normal services

If the application is not a Web application, or is only an HSF service or API interface service invoked to other application servers (pure Server to Server on the Intranet, using AKSK plus signature to verify signatures instead of Login), CSRF does not need to be configured. Please provide the corresponding verification code for the corresponding q&A or security engineer to confirm and close the vulnerability.

two.Security Package Import

Step1.Configuring an Extension PackagePOMRely on

Note: After the introduction of the SpringMVC extension security package, a series of switches, including the XSS switch and the CSRF switch, will be enabled by default, resulting in a temporary service exception (garbled characters on the front page, 403 status code returned from interface access, etc.). You only need to continue operations according to the document, and the service will eventually recover to normal.

1. SpringMVC extension package

Refer to the SpringMVC Security Extension Introduction documentation on the Web

2 SpringBoot Extension package (Starter)

Refer to the SpringBoot Security Extension introduction documentation online

Step2 check whether the dependency succeeds

After the POM is configured, check whether the following packages exist in the External Libraries of IDEA

/ / for SpringMVC only check this package com. Alibaba. Security: security - spring - webmvc / / SpringBoot only check this package com.alibaba.security:security-spring-boot-starterCopy the code

three. CSRFSwitch configuration

Step1.Explicit configurationCSRFswitch

CSRF interception is automatically enabled after the security package is introduced, but to ensure readability of the configuration and facilitate troubleshooting, please negotiate the following configuration in the “application.properties” file under Resources (if not, please create) :

spring.security.csrf.enabled = true
Copy the code

Note: After this switch is enabled, all access requests will be blocked because no token is brought in. Therefore, you need to continue the configuration to restore services

Step2.tokenBring to the front

Once the switch is configured, the security package generates a random string called CSRF_Token, which is stored in a cookie by default. If VM is used, it can be obtained by invoking the relevant interface through the VM.

This Token needs to be passed to the server as a parameter in every add, delete, or change interface request on the front end to verify security

Different front-end technology solutions have different ways to bring:

1 VMThe back-end template

A. The VM back-end template supports the following configuration modes:

  • Unified configuration in application.properties
  • CSRF Token Automatically generates a list of URL mappings with multiple values separated by commas (default is null)
  • The current URL for the ant style, the style value by a spring configuration items. Security. CSRF. URL. Style decision
 spring.security.csrf.token.urls = /csrf_token/**
Copy the code

B. Use the @cSRFTokenModel annotation at the Controller class level

@Controller @RequestMapping("/csrf") @CsrfTokenModel public class CsrfController { @RequestMapping("/form") public String form() { return "csrf_form"; }}Copy the code

C. Use annotations at the Controller class level

This can cause all templates under the controller to render. The token parameter name and value can be obtained through macros

Use the annotation @cSRFTokenModel configuration at the method level

@Controller @RequestMapping("/csrf") public class CsrfController { @RequestMapping("/form") @CsrfTokenModel public String form() { return "csrf_form"; }}Copy the code

If there are too many controllers or methods that require CSRF Token verification, the current framework also provides a convenient method, that is, automatic generation of URL mapping level. You only need to add the following configuration in the application.properties file:

  • CSRF Token Automatically generates a list of URL mappings with multiple values separated by commas (default is null)

  • The current URL style as the regular expression, style value by a spring configuration items. Security. CSRF. URL. Style decision

 spring.security.csrf.token.urls = /csrf_token/**
Copy the code
  • CSRF Token model attribute name
spring.security.csrf.token.model.attribute = csrfToken
Copy the code

After the back-end configuration is complete, add fields to all request forms in the VM template to ensure that each request carries them

  • Velocity Template Code
     <form method="post" action="/form/submit">
         <input type="hidden" name="${csrfToken.parameterName}"      value="${csrfToken.token}">
         <input type="text" name="name"/>
         <br>
         <input type="submit" value="Submit"/>
     </form>
Copy the code
  • The rendered HTML
<form method="post" action="/form/submit">
    <input type="hidden" name="_csrf" value="bfe23341-b28c-41a3-bed8-dfbd65385fc8">
    <input type="text" name="name"/>
    <br>
    <input type="submit" value="Submit"/>
</form>
Copy the code

In normal cases, as shown in the figure above, after rendering, field name is p_cSRf, value is a randomly generated value, and the corresponding field will be put in cookie. Note that the token field name must be extracted from the CSRftoken obJ and cannot be customized on the front end. To change the field name on the back end, please refer to the “CSRF customization feature” below.

2. ajaxFront end separation

In the case of Ajax requests, the token cannot be directly rendered to the page.

  • The token is read in the cookie and carried into the parameters of the Ajax request. Then pass it to the back end (the default key of the token in the Cookie is xSRF-token)
  • If the xSRF-token value in the cookie cannot be read by JS, please check that the httponly attribute of the value is not true. If it is true, please add a configuration item in “application.properties” as follows:
  • If it is carried in a parameter, the default Token name is _csrf. If it is carried in a header, the default Token name is X-xsrF-token
spring.security.csrf.cookieHttpOnly = false
Copy the code
  • After the configuration, clear the browser cache and try to obtain the XSRF-token value again

3.Under the cross domaintokentransmission

In common service scenarios, the security package stores the token in the cookie domain name corresponding to the server. The token can be invoked by the front-end JS and implanted into the header or parameters. However, in a cross-domain scenario, the domain name of the front-end page and back-end server are different. As a result, cookies under the domain name of the server cannot be obtained.

Suppose aaAA.com wants to access the bbbb.com interface across domains, and the BBbb.com interface performs CSRF verification. In this case, perform the following steps for token exchange:

The service solution for enabling CORS cross-domain headers is as follows:

1. bbbb.comAdd an interface that returns its owncsrf token

An example of this interface is as follows:

    @RequestMapping(value = "/ajax", produces = MediaType.APPLICATION_JSON_VALUE)
    @CrossOrigin(origins = "http://aaaaaa.com:7001", maxAge = 3600)
    @ResponseBody
    public CsrfToken getCsrfToken(HttpServletRequest request, HttpServletResponse response) {
        CsrfToken csrfToken = csrfTokenRepository.loadToken(request);
        if (csrfToken == null) {
            csrfToken = csrfTokenRepository.generateToken(request);
            csrfTokenRepository.saveToken(csrfToken, request, response);
        }
        return csrfToken;

    }

Copy the code
2. aaaa.comcarrywith-credentialsTo get thetoken
function callOtherDomain(){ var xhr = new XMLHttpRequest(); if(xhr) { xhr.open('GET', 'http://bbbbbb.com:7001/csrf/ajax', true); xhr.withCredentials = true; xhr.onload = function () { result.innerHTML = xhr.responseText; var json = JSON.parse(xhr.responseText); token_key = json.paramterName; token = json.token; }; xhr.send(null); }}Copy the code
3. Store the obtained token on the client (such as localStorage or hidden fields on the page)
4. When aaAA.com accesses other interfaces of BBbb.com, the token is obtained and passed to bbbb.com as interface parameters or header parameters. At the same time, the withcredentials = true should be set:
function buttonClick(token_key, token){ var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://bbbbbb.com:7001/csrf/cors/check'); xhr.withCredentials = true; xhr.onload = function () { result.innerHTML = xhr.responseText; }; xhr.onerror = function () { result.innerHTML = "Error!" ; } xhr.send(token_key + '=' + token + '&' + otherparams) }Copy the code

Step3. Verify the Token on the backend

Token verification on the backend only provides global URL check. By default, token check is performed on all POST requests without explicit configuration. To better support services, you are advised to explicitly configure application.properties in classpath.

/ / configure interceptor GET request, according to the business needs security requires a POST request to intercept spring. Security. CSRF. SupportedMethods = POST, GET / / configuration using ant style needs to check token url (safety requirements for all increase authorization token validation) spring. Security. CSRF. Url. The included = / * * / / use ant style configuration without the need for check the url of the token, can only query interface for excluded spring. Security. CSRF. Url. The excluded = / CSRF nocheckCopy the code

After verification, if it is successful, the corresponding background function will be successfully executed; if it fails, the status code 403 will be returned or 301 will jump to Taobao. Error, as follows:

status : 403
message : Invalid CSRF Token '' was found on the request parameter 'p_csrf' or header 'h_csrf'.
=== 
status: 301
location: err2.taobao.com
Copy the code