yii2 defense mechanisms attack csrf

csrf, Chinese name: cross-site request forgery, you can search on Baidu information, learn more about the concepts in this regard. For us it is very helpful.
csrf of yii2 function is to achieve the realization of functions in yii \ web \ request class.
request class attributes, the default is true.
public $ enableCsrfValidation = true;
we request component in the configuration file can be configured in the value
request => [
'enableCookieValidation' => to true,
]
which is globally available, each request that is a post, will enable csrf the attack defense function, namely to verify.
Simply put, the entire access policy as follows:

(1) by Yii :: $ app-> when request-> csrfToken first visit to obtain csrfToken, directly to getCsrfToken () access

public function getCsrfToken($regenerate = false)
    {
 
        if ($this->_csrfToken === null || $regenerate) {
            if ($regenerate || ($token = $this->loadCsrfToken()) === null) {
                $token = $this->generateCsrfToken();
            }
            // the mask doesn't need to be very random
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.';
            $mask = substr(str_shuffle(str_repeat($chars, 5)), 0, static::CSRF_MASK_LENGTH);
            // The + sign may be decoded as blank space later, which will fail the validation
            $this->_csrfToken = str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));
        }
        return $this->_csrfToken;
}

 Each visit $ this -> _ csrfToken will be equal to null, $ regenerate default equals false. So then performed $ token = $ this-> loadCsrfToken () function.

 

protected function loadCsrfToken()
    {
        if ($this->enableCsrfCookie) {
            return $this->getCookies()->getValue($this->csrfParam);
        } else {
            return Yii::$app->getSession()->get($this->csrfParam);
        }
}

 

 Go to the cookie obtain $ _COOKIE [ '_ csrf'] this token, this token because the first visit will certainly not exist, it returns null. So they will go to perform $ this-> generateCsrfToken ().

 

protected function generateCsrfToken()
    {
        $token = Yii::$app->getSecurity()->generateRandomString();
        if ($this->enableCsrfCookie) {
            $cookie = $this->createCsrfCookie($token);
            Yii::$app->getResponse()->getCookies()->add($cookie);
        } else {
            Yii::$app->getSession()->set($this->csrfParam, $token);
        }
 
        return $token;
}

 

 This function is free to create a token string, and then save it in $ _COOKIE [ '_ csrf'] in. In this way the root directory of the site /, COOKIE there is a token of this, and returns a token. Value as long as we do not shut down the entire page, then the $ _COOKIE [ '_ csrf'] is not become, it represents a unique voucher native client.
Next look at getCsrfToken () function in these few lines of code:
$ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.';
$ Mask = substr (str_shuffle (str_repeat ($ chars,. 5)), 0, static :: CSRF_MASK_LENGTH);
// of The + Sign On May BE Decoded AS blank Space later, Which Will Fail The Validation
$ the this - '.'.> _ csrfToken = str_replace ( '+',, the base64_encode ($ mask $ this-> xorTokens ($ token, $ mask)) );
here and using token strings, encoded and returned by enciphering _csrfToken 64, i.e. the value of the acquired csrfToken.
(2) second visit, Yii :: $ app-> request-> csrfToken, due to the $ token = $ this-> loadCsrfToken ( ) function can already get access to the token, that is, access to the Web of $ _COOKIE [ ' _csrf '
(3) then we need to post data in the past, we will be validated in yii \ web \ conreoller class of beforeAction ($ action) function

public function beforeAction($action)
{
    if (parent::beforeAction($action)) {
        if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) {
            throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));
        }
        return true;
    }
    
    return false;
}

 By Yii :: $ app-> getRequest () -> validateCsrfToken () function to verify

 

public function validateCsrfToken($token = null)
    {
        $method = $this->getMethod();
 
        // only validate CSRF token on non-"safe" methods http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
        if (!$this->enableCsrfValidation || in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {
            return true;
        }
        $trueToken = $this->loadCsrfToken();
 
        var_dump($trueToken);
 
        if ($token !== null) {
            return $this->validateCsrfTokenInternal($token, $trueToken);
        } else {
            // As long as there is a true, real returns
            return ($this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken) || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken));
        }
}

 

 Returns true representatives certified by the representatives of false failure for GET, HEAD ',' OPTIONS ' , this approach is not certified, return true, by default, can continue to access.

If other access methods, such as POST, then certification.
$ trueToken = $ this-> loadCsrfToken ( ); the presence of this for a complete COOKIE [ '_ csrf'] true token.

Look at $ this-> validateCsrfTokenInternal ($ this-> getBodyParam ($ this-> csrfParam), $ trueToken);
inside it a $ this-> getBodyParam ($ this-> csrfParam). Value is to get the post over csrfToken value or form, then validateCsrfTokenInternal ($ token, $ trueToken) , this function will csrfToken decrypt (since before the adoption of Yii :: $ app-> request-> csrfToken this value, is encrypted the, so now we want to decrypt). Value after decrypting it and $ trueToken Returns true if the same words.

Look at $ this-> validateCsrfTokenInternal ($ this-> getCsrfTokenFromHeader (), $ trueToken) This sentence is by $ this-> value to get the value csrfToken in the head, and then decrypt, decrypt after getCsrfTokenFromHeader () if and $ it returns true trueToken the same words.

 Note that the return ($ this-> validateCsrfTokenInternal ($ this-> getBodyParam ($ this-> csrfParam), $ trueToken) || $ this-> validateCsrfTokenInternal ($ this-> getCsrfTokenFromHeader (), $ trueToken));
 this one is determined ($ this-> validateCsrfTokenInternal ($ this- > getBodyParam ($ this-> csrfParam), $ trueToken) || $ this-> validateCsrfTokenInternal ($ this-> getCsrfTokenFromHeader (), $ trueToken)) after authentication by decrypting mode is equivalent to return (true || false), which is determined by || parentheses is true as long as there is a true, return true

so that once generated and stored in the token COOKIE [ '_ csrf'], then every time when the access to the token will encrypt data as a reference for generating a random csrfToken, then returned to the form. When the post data over, you have this csrfToken passed over, and then decrypt, and re-token COOKIE [ '_ csrf'] are compared, it shows that if equal access is not offensive, is to visit this site. If access is not by describing the possible deletion of some information it is not secure.

 

Guess you like

Origin www.cnblogs.com/niuben/p/11057406.html