
De nombreuses applications utilisent des jetons Web JSON (JWT) pour permettre au client de s'identifier pour un échange d'informations ultérieur après l'authentification.
JSON Web Token est une norme ouverte (RFC 7519) qui définit une manière compacte et autonome de transférer en toute sécurité des informations entre les parties en tant qu'objet JSON.

Ces informations sont vérifiées et fiables car elles sont signées numériquement.
Les JWT peuvent être signés à l'aide d'un secret (à l'aide de l'algorithme HMAC) ou de paires de clés publiques / privées à l'aide de RSA ou ECDSA.
Le jeton Web JSON est utilisé pour transmettre des informations concernant l'identité et les caractéristiques du client. Ce «conteneur» est signé par le serveur afin que le client n’interfère pas avec lui et ne puisse pas changer, par exemple, les données d’identification ou les caractéristiques (par exemple, le rôle d’un simple utilisateur à un administrateur ou changer la connexion du client).
Ce jeton est créé en cas d'authentification réussie et est vérifié par le serveur avant de commencer à exécuter chaque demande client. Le jeton est utilisé par l'application comme une «carte d'identité» du client (un conteneur contenant toutes les informations le concernant). Le serveur a la possibilité de vérifier la validité et l'intégrité du jeton de manière sûre. Cela permet à l'application d'être sans état (l'application sans état n'enregistre pas les données client générées dans une session pour une utilisation dans la prochaine session avec ce client (chaque session est indépendante)), et le processus d'authentification est indépendant des services utilisés (dans le sens où les technologies client et serveur peut varier, y compris même le canal de transport, bien que HTTP soit le plus couramment utilisé).
Considérations pour l'utilisation de JWT
Même si le jeton JWT est facile à utiliser et vous permet de fournir des services (principalement REST) sans état (sans état), cette solution ne convient pas à toutes les applications, car elle comporte certaines mises en garde, telles que la question du stockage du jeton.
Si l'application ne doit pas être complètement sans état, vous pouvez envisager d'utiliser le système de session traditionnel fourni par toutes les plateformes Web. Cependant, pour les applications sans état, JWT est une bonne option s'il est implémenté correctement.
Problèmes et attaques JWT
Utilisation de l'algorithme de hachage NONE
Une attaque similaire se produit lorsqu'un attaquant modifie le jeton et modifie également l'algorithme de hachage (champ «alg») pour indiquer via le mot clé none que l'intégrité du jeton a déjà été vérifiée. Certaines bibliothèques ont vu les jetons signés en utilisant l'algorithme none comme un jeton valide avec une signature vérifiée, de sorte qu'un attaquant pourrait modifier la charge utile du jeton et l'application ferait confiance au jeton.
Pour empêcher une attaque, vous devez utiliser la bibliothèque JWT, qui n'est pas affectée par cette vulnérabilité. De plus, lors de la validation du token, vous devez explicitement demander l'utilisation de l'algorithme attendu.
Exemple d'implémentation:
Interception de jetons
L'attaque se produit lorsqu'un jeton a été intercepté ou volé par un attaquant et qu'il l'utilise pour accéder au système en utilisant les informations d'identification d'un utilisateur spécifique.
La protection consiste à ajouter un «contexte utilisateur» au token. Le contexte utilisateur comprendra les informations suivantes:
- Une chaîne aléatoire générée au stade de l'authentification et incluse dans le jeton, et également envoyée au client sous forme de cookie plus sécurisé (indicateurs: préfixes HttpOnly + Secure + SameSite + cookie).
- Le hachage SHA256 de la chaîne aléatoire sera stocké dans le jeton afin qu'aucun problème XSS ne permette à l'attaquant de lire la valeur de la chaîne aléatoire et de définir le cookie attendu.
L'adresse IP ne sera pas utilisée dans le contexte, car il existe des situations dans lesquelles l'adresse IP peut changer au cours d'une session, par exemple, lorsqu'un utilisateur accède à l'application via son téléphone portable. L'adresse IP change alors légitimement en permanence. De plus, l'utilisation d'une adresse IP peut potentiellement poser des problèmes au niveau de la conformité au RGPD européen.
Si, lors de la vérification du jeton, le jeton reçu ne contient pas le contexte correct, il doit être rejeté.
Exemple d'implémentation:Code pour créer un jeton après une authentification réussie:
Code pour vérifier la validité du jeton:
Révocation explicite du jeton par l'utilisateur
Étant donné que le jeton ne devient invalide qu'après son expiration, l'utilisateur n'a pas de fonction intégrée qui vous permet d'annuler explicitement le jeton. Ainsi, en cas de vol, l'utilisateur ne peut pas retirer lui-même le jeton puis bloquer l'attaquant.
L'une des méthodes de protection est l'introduction d'une liste noire de jetons, qui conviendra pour simuler la fonction de «déconnexion» qui existe dans un système de session traditionnel.
La collection (dans le codage SHA-256 en HEX) du jeton avec la date d'annulation, qui devrait dépasser la période de validité du jeton émis, sera stockée dans la liste noire.
Lorsque l'utilisateur souhaite se "déconnecter", il appelle un service spécial qui ajoute le jeton utilisateur fourni à la liste noire, ce qui entraîne l'annulation immédiate du jeton pour une utilisation ultérieure dans l'application.
Exemple d'implémentation:Dépôt de la liste noire:Pour le stockage centralisé de la liste noire, une base de données avec la structure suivante sera utilisée:
create table if not exists revoked_token(jwt_token_digest varchar(255) primary key, revokation_date timestamp default now());
Gestion de la révocation des jetons:
Divulgation de jetons
Cette attaque se produit lorsqu'un attaquant accède à un jeton (ou à un ensemble de jetons) et extrait les informations qu'il contient (les informations sur le jeton JWT sont codées à l'aide de base64) pour obtenir des informations sur le système. Les informations peuvent être, par exemple, telles que les rôles de sécurité, le format de connexion, etc.
La méthode de protection est assez évidente et consiste à chiffrer le jeton. Il est également important de protéger les données chiffrées contre les attaques utilisant la cryptanalyse. Pour atteindre tous ces objectifs, l'algorithme AES-GCM est utilisé, qui fournit le chiffrement authentifié avec les données associées (AEAD). La primitive AEAD fournit une fonctionnalité de chiffrement authentifié symétrique. Les implémentations de cette primitive sont protégées contre les attaques adaptatives basées sur un texte chiffré sélectionné. Lors du cryptage du texte en clair, vous pouvez éventuellement spécifier des données connexes qui doivent être authentifiées mais non cryptées.
En d'autres termes, le chiffrement avec les données pertinentes garantit l'authenticité et l'intégrité des données, mais pas leur secret.
Cependant, il convient de noter que le chiffrement est ajouté principalement pour masquer les informations internes, mais il est très important de se rappeler que la protection initiale contre la contrefaçon du jeton JWT est la signature.Par conséquent, la signature du jeton et sa vérification doivent toujours être utilisées.
Stockage de jetons côté client
Si l'application stocke le jeton de sorte qu'une ou plusieurs des situations suivantes se produisent:
- le token est automatiquement envoyé par le navigateur (stockage des cookies);
- le jeton est obtenu même si le navigateur est redémarré (en utilisant le conteneur localStorage du navigateur);
- le jeton est obtenu dans le cas d'une attaque XSS (cookie disponible pour le code JavaScript ou un jeton stocké dans localStorage ou sessionStorage).
Pour empêcher une attaque:
- Stockez le jeton dans le navigateur à l'aide du conteneur sessionStorage.
- Ajoutez-le à l'en-tête d'autorisation à l'aide du schéma de support. Le titre devrait ressembler à ceci:
Authorization: Bearer <token>
- Ajoutez des informations d'empreintes digitales au jeton.
En stockant le jeton dans le conteneur sessionStorage, il fournit un jeton pour le vol dans le cas de XSS. Cependant, une empreinte digitale ajoutée au jeton empêche un attaquant de réutiliser le jeton volé sur son ordinateur. Pour fermer les zones d'utilisation maximale d'un attaquant, ajoutez une stratégie de sécurité du contenu pour limiter le contexte d'exécution.
Il reste un cas où un attaquant utilise le contexte de navigation de l'utilisateur comme serveur proxy pour utiliser l'application cible via un utilisateur légitime, mais la politique de sécurité du contenu peut empêcher la communication avec des domaines inattendus.
Il est également possible d'implémenter un service d'authentification afin que le jeton soit émis à l'intérieur d'un cookie sécurisé, mais dans ce cas, une protection contre CSRF doit être implémentée.
Utilisation d'une clé faible pour créer un jeton
Si le secret utilisé dans le cas de l'algorithme HMAC-SHA256, nécessaire à la signature du jeton, est faible, il peut être piraté (récupéré à l'aide d'une attaque par force brute). En conséquence, un attaquant peut truquer un jeton valide arbitraire en termes de signature.
Pour éviter ce problème, vous devez utiliser une clé secrète complexe: alphanumérique (casse mixte) + caractères spéciaux.
La clé n'étant nécessaire que pour les calculs informatiques, la taille de la clé secrète peut dépasser 50 positions.
Par exemple:
A&'/}Z57M(2hNg=;LE?~]YtRMS5(yZ<vcZTA3N-($>2j:ZeX-BGftaVk`)jKP~q?,jk)EMbgt*kW'
Pour évaluer la complexité de la clé secrète utilisée pour votre signature de jeton, vous pouvez appliquer une attaque par dictionnaire de mot de passe au jeton en combinaison avec l'API JWT.