4
votes

Pourquoi _token et XSRF-TOKEN diffèrent-ils dans Laravel?

Je ne comprends pas pourquoi le jeton pour les requêtes AJAX (XSRF-TOKEN) est différent d'un _token par les formulaires normaux. En plus, c'est beaucoup plus long. Pourquoi? Et pourquoi avoir 2 jetons du tout? Pourquoi ne pas en utiliser un qui serait le même pour les requêtes ajax et normales?


3 commentaires

"Laravel stocke le jeton CSRF actuel dans un cookie XSRF-TOKEN chiffré qui est inclus avec chaque réponse générée par le framework." laravel.com/docs/8.x/csrf#csrf-x-csrf-token


Pourquoi chiffré? .


stackoverflow.com/a/34783845/2797224


4 Réponses :


0
votes

Si vous jetez un œil à vendor/laravel/framework/src/Illuminate/Session/Store.php il existe une méthode nommée regenerateToken qui créera le jeton pour l'application

    /**
     * Regenerate the CSRF token value.
     *
     * @return void
     */
    public function regenerateToken()
    {
        $this->put('_token', Str::random(40));
    }

Ensuite, le jeton que vous obtenez de la session ou de JS (qui provient également de la session), ils ont tous la même longueur de 40 caractères et le jeton est juste un simple caractère aléatoire de 40 qui est stocké dans votre session. il n'est ni chiffré ni haché car seul vous, l'utilisateur, avez accès à la session car si je veux attaquer CSRF depuis une source extérieure, la source n'a pas accès à la session, donc fondamentalement, il n'est pas nécessaire de hacher ou de crypter cette longueur de 40 jeton.

Note latérale : le jeton n'est pas chiffré par lui-même, toutes les sessions sont chiffrées en laravel par défaut.


0 commentaires

0
votes

Voici ce que dit la documentation sur le XSRF:

https://laravel.com/docs/8.x/csrf#csrf-x-xsrf-token

Donc, fondamentalement, sa valeur de _token est chiffrée et enregistrée dans les cookies


0 commentaires

1
votes

1 approche, 2 techniques

Laravel utilise 2 techniques distinctes pour empêcher les attaques CSRF.

Les approches sont les mêmes:

pour envoyer un jeton (CSRF ou XSRF) au client et au client doivent le renvoyer dans la demande suivante

et il y a 2 étapes:

  • le serveur envoie un jeton (obtenir un formulaire) (CSRF ou XSRF)
  • jeton de retour client en tant que jeton X (publier un formulaire) (X-CSRF ou X-XSRF)

lorsque vous voyez un jeton X, c'est un client qui a répondu que le client envoie avec la poste au serveur

La raison pour laquelle nous avons 2 techniques n'est pas ces utilisations différentes approches ,

C'est parce que les architectures côté client de l'application Web utilisant 2 architectures différentes:

  • old-fashion: le serveur génère du HTML pur et l'envoie au client
  • Application à page unique: le client SPA Framework (comme Vue, React, Angular) envoie et reçoit des données au format Json ou Xml et crée le bon Html dans Dom

Maintenant, CSRF-Protection Technics s'adapte avec ces deux architectures côté client comme ci-dessous:

$token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized()));

Description du mécanisme

1.Le serveur génère un jeton

Laravel crée un jeton CSRF (40 caractères) et le stocke en session

$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');

Après avoir généré et stocké le jeton en session, le jeton sera envoyé au client en tant que CSRF et XSRF

Le côté client décidera d'utiliser ce qu'il veut.

2.Le serveur envoie un jeton au client

pour le client à l'ancienne (technique de synchronisation de jeton) peut recevoir le jeton CSRF sous deux formes avec appel à la méthode d'assistance csrf_token() dans la lame:

  1. dans le corps du formulaire: <input type='hidden' name='_token' value='{{csrf_token()}}' />
  2. dans la balise meta que la requête Ajax peut utiliser dans son en-tête

voici comment cette méthode d'assistance renvoie la valeur correspondante:

   /**
     * Determine if the session and input CSRF tokens match.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function tokensMatch($request)
    {
        $token = $this->getTokenFromRequest($request);// it get token from request

        return is_string($request->session()->token()) &&
               is_string($token) &&
               hash_equals($request->session()->token(), $token); //checks if it is equal to session token or not
    }



/**
     * Get the CSRF token from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string
     */
    protected function getTokenFromRequest($request)
    {
        $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');//check sync-token

        if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
            $token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized()));
        }

        return $token;
    }

pour le framework client cookie-header (SPA Frameworks) (comme Angular) peut recevoir un jeton XSRF dans le cookie car :

il n'y a pas de formulaire Html générant dans le serveur quel serveur peut y amorcer son entrée cachée. et La façon dont il peut envoyer son jeton au client l'envoie avec un cookie. (Cette méthode nommée XSRF)

$this->addCookieToResponse($request, $response);

Laravel a mis le jeton aux deux endroits car il appartient au client de déterminer la méthode à utiliser et s'attend à ce que le client réponde à l'une de ces méthodes.

3.Le client envoie un jeton X au serveur

Côté client:

  1. à l'ancienne (X-CSRF):
  • jeton de publication dans les données de publication ou:
  • faites un appel ajax comme ceci:
$this->tokensMatch($request)
  1. Framework SPA: ces frameworks placent le jeton en tant que X-XSRF-TOKEN dans les en-têtes de publication

  2. Le serveur vérifie le jeton X-Token contre le jeton en session


Il est maintenant temps pour Laravel de vérifier le jeton

dans VerifyCSRFMiddleware, Laravel vérifie si la demande doit être vérifiée pour le jeton de protection CSRF qu'elle vérifie:

/**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     *
     * @throws \Illuminate\Session\TokenMismatchException
     */
    public function handle($request, Closure $next)
    {
        if (
            $this->isReading($request) ||
            $this->runningUnitTests() ||
            $this->inExceptArray($request) ||
            $this->tokensMatch($request) //compares request_token vs session_token
        ) {
            return tap($next($request), function ($response) use ($request) {
                if ($this->shouldAddXsrfTokenCookie()) {
                    $this->addCookieToResponse($request, $response); //add cookie to response
                }
            });
        }

        throw new TokenMismatchException('CSRF token mismatch.');
    }

Deux lignes sont intéressantes:

`$.ajaxSetup({
           headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
           }
          });`

et

/**
     * Add the CSRF token to the response cookies.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Symfony\Component\HttpFoundation\Response  $response
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function addCookieToResponse($request, $response)
    {
        $config = config('session');

        $response->headers->setCookie(
            new Cookie(
                'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
                $config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
            )
        );

        return $response;
    }

il y a donc plusieurs données dans chaque requête que le serveur peut mettre:

  1. html form input _token (40 caractères) ( C SRF)
  2. html meta header csrf-token (40 caractères) ( C SRF)
  3. cookie XSRF-TOKEN (224 caractères) ( X SRF)

et plusieurs données peuvent être envoyées par le client au serveur en réponse aux jetons

  1. post paramètre _token (40 caractères) (X- C SRF)
  2. En-tête http X-CSRF-TOKEN (40 caractères) (X- C SRF)
  3. En-tête http X-XSRF-TOKEN (224 caractères) (X- X SRF)

Pourquoi dans le jeton CSRF il y a 40 caractères et dans XSRF il y a 224 caractères? Nous y arriverons un peu plus tard

La requête Http doit correspondre au jeton avec l'un des X-Token ci- dessus

/**
     * Get the CSRF token value.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    function csrf_token()
    {
        $session = app('session');

        if (isset($session)) {
            return $session->token();
        }

        throw new RuntimeException('Application session store not set.');
    }

le premier modèle à examiner est sync-token, le jeton du client peut être dans un <input name='_token' /> ou il peut être dans Http Header si demandé à partir d'un appel de méthode Ajax dans le client.

la ligne

/**
     * Regenerate the CSRF token value.
     *
     * @return void
     */
    public function regenerateToken()
    {
        $this->put('_token', Str::random(40));
    }

vérifiera cela et s'il peut être récupéré, il reviendra et vérifiera via le session_token

mais if (! $token est NULL il vérifiera le modèle d'en-tête de cookie:

obtenir $header = $request->header('X-XSRF-TOKEN') partir de l'en-tête et le déchiffrer, si son besoin de déchiffrement

+-------------+-----------------+-----------+------------+
| Client Arch | Protection Tech | Get Token | Post Token |
+-------------+-----------------+-----------+------------+
| old-fashion | sync-token      | CSRF      | X-CSRF     |
| SPA         | cookie-header   | XSRF      | X-XSRF     |
+-------------+-----------------+-----------+------------+

s'il a été crypté avant d'être ajouté au cookie

Cryptage des cookies

C'est la raison pour laquelle le jeton XSRF pourrait être 224chars: Cryptage des cookies et vous pouvez désactiver le cryptage des cookies et rendre le jeton XSRF 40 caractères, comme le jeton CSRF

La différence était donc pour le cryptage des cookies.

Nécessité du cryptage des cookies

Mais pourquoi les cookies doivent-ils être chiffrés? Pourquoi le cookie XSRF doit-il être chiffré?

En général, Laravel Store certaines données sur les cookies et les cookies peuvent être modifiés par le client. parce que le serveur ne veut pas de modifications sur le client, il crypte les cookies . cela peut être configuré pour ne pas crypter le cookie CSRF car il n'est pas soumis à des modifications par l'utilisateur et il est uniquement sujet à être volé par le détournement de cookie, lequel cryptage ne va pas empêcher cet événement.

La seule différence qu'il fait est d'avoir à token (non chiffré et chiffré) pour deux méthodes de protection CSRF. Donc, si les attaquants peuvent accéder à un jeton stocké dans un cookie (X-XSRF) (étant donné que le piratage> Cookie est beaucoup plus facile à détourner du html et du css d'exécution avec XSS), il ne peut pas être abusé avec le mécanisme de jeton de synchronisation. Depuis l'attaque CSRF avec le paramètre de forme http est plus facile puisque le HTML peut être dans le courrier électronique ou etc. alors que Runnig Js est moins courant.

Conclusion

Donc, si un client utilise un architecte client à l'ancienne . la technique d'en-tête de cookie> (XSRF stocké dans Cookie) ne le laissera pas avec une fuite de données dans le cookie .

plus d'informations sur ces modèles de prévention peuvent être trouvées ici:

https://en.wikipedia.org/wiki/Cross-site_request_forgery#Prevention


0 commentaires

0
votes

La réponse courte est que XSRF-TOKEN est crypté CSRF-TOKEN, c'est exactement ce que c'est. Le cryptage se terminera par une chaîne beaucoup plus longue que l'original.

La raison pour laquelle il existe pour commencer est (comme mentionné dans la documentation):

Ce cookie est principalement envoyé par commodité car certains frameworks et bibliothèques JavaScript, comme Angular et Axios, placent automatiquement sa valeur dans l'en-tête X-XSRF-TOKEN sur les requêtes de même origine.

Cela signifie que lorsque vous utilisez un framework ou une bibliothèque qui définit automatiquement l'en-tête X-XSRF-TOKEN dans une demande si le cookie XSRF-TOKEN est présent, vous n'aurez pas à vous soucier de transmettre le jeton CSRF à chaque demande car cela est fait automatiquement.

Personnellement, je ne suis pas sûr à 100% que la déclaration du manuel soit actuellement exacte ou qu'elle soit réellement utile. Personnellement, j'ai fini par supprimer complètement ce cookie à cause d'un pare-feu mal configuré que certains de nos clients utilisent pour supprimer les longs cookies, et jusqu'à présent, je ne l'ai pas manqué.


0 commentaires