🗝️JSON Web Token

JWT

Contournement d'authentification via signature non vérifiée

Etapes:

  • Surlignez le payload de votre JWT sur Burp

  • Dans Burp Inspector, changez la valeurs de votre nom d'utilisateur (exp: "username":"user123 => "username":"administrator")

  • Cliquez sur "apply changes"

  • Envoyez la requête

  • Constater que vous êtes connecté en temps que "administrator"

Contournement d'authentification via signature nulle

Etapes:

  • Surlignez le header de votre JWT sur Burp

  • Dans Burp Inspector, changer l'algorithme de chiffrement du token en "none" (exp: "alg":"RS256" => "alg":"none")

  • Cliquez sur "apply changes"

  • Surlignez le payload de votre JWT sur Burp

  • Dans Burp Inspector, changez la valeurs de votre nom d'utilisateur (exp: "username":"user123 => "username":"administrator")

  • Cliquez sur "apply changes"

  • Supprimez la signature (attention: gardez le "." à la fin du payload)

  • Envoyez la requête

  • Constater que vous êtes connecté en temps que "administrator"

Brute force du secret

Si le JWT utilise un chiffrement faible tel que HS256 il est possible de bruteforce le secret de la signature avec hashcat comme ceci:

$ hashcat -a 0 -m 16500 <jwt> <wordlist>

Une fois le secret trouvé, on peut alors générer de nouveaux token comme on le souhaite.

On peut utiliser l'extension JWT Editor de Burp Suite pour ce faire.

Ressource:

https://portswigger.net/web-security/jwt/working-with-jwts-in-burp-suite#adding-new-signing-keys

Contournement d'authentification via injection d'en-tête jwk

JWK (JSON Web Key) est un format standardisé permettant de représenter les clés sous forme d'objet JSON.

Prérequis: Extension JWT Editor de Burp Suite

Etapes:

  • Allez dans l'onglet d'extension JWT Editor Keys

  • Cliquez sur "New RSA key" > "Generate" > "OK"

  • Interceptez la requête voulu

  • Allez dans l'onglet "JSON Web Token"

  • Changez votre nom d'utilisateur par celui de votre cible dans le payload

  • Cliquez sur "Attack" > "Embedded JWK"

  • Sélectionnez la clé RSA précédemment générée puis lancez l'attaque

  • Remarquez qu'un paramètre "jwk" contenant votre clé a été ajouté au payload

  • Envoyez la requête et retournez sur votre navigateur

  • Remarquez que vous êtes maintenant connecté sur compte de votre cible

Contournement d'authentification via injection d'en-tête jku

JKU (JWK Set URL) est un URI qui fait référence à une ressource pour un ensemble de clés publiques encodées en JSON, dont l'une correspond à la clé utilisée pour signer numériquement le JWS (JSON Web Signature)

Prérequis: Extension JWT Editor de Burp Suite

Etapes:

  • Allez dans l'onglet d'extension JWT Editor Keys

  • Cliquez sur "New RSA key" > "Generate" > "OK"

  • Interceptez la requête voulu

  • Allez dans l'onglet "JSON Web Token"

  • Changez votre nom d'utilisateur par celui de votre cible dans le payload

  • Cliquez sur "Attack" > "Embedded JWK"

  • Sélectionnez la clé RSA précédemment générée puis lancez l'attaque

  • Remarquez qu'un paramètre "jwk" contenant votre clé a été ajouté au payload

  • Copier le contenu du paramètre "jwk" et supprimer le paramètre ainsi que son contenu

{
        "kty": "RSA",
        "e": "AQAB",
        "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
        "n": "qCjZDCcGtvsnLxro6OxWapUxUIqO4NP0WKWAmOcNUn-VKr0C4sVnNjx9AkpREfDU9GhUuvLqjxQYjRt9JjE5dkOi3W43kwCHm-zbVaI2Bjt0_XpyBGi1INiD1lrNl9UWo5PykdwN3j_ByJ9tiDVgrHUmuLXV3THju7XluPlQ5B-c7nZQx0zqMqYnihFSKeUuZwIL0KIPAEwVZpCg0WBOgHIaSDybuuKw5sAUQ4W9SuVTNXZ1DEOB7fRAE6eidRPMxUNS9sAcOEWohhe3ZYCQO0tNVM5asn3YUQBMHlxsu317YydnM4AS82Y61eu7Vr-nnf-lIpTEco00U_LL9dcb4Q"
 }
  • Ecrivez votre exploit sur votre serveur d'attaque avec les données copiées

{
  "keys": [
    {
        "kty": "RSA",
        "e": "AQAB",
        "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
        "n": "qCjZDCcGtvsnLxro6OxWapUxUIqO4NP0WKWAmOcNUn-VKr0C4sVnNjx9AkpREfDU9GhUuvLqjxQYjRt9JjE5dkOi3W43kwCHm-zbVaI2Bjt0_XpyBGi1INiD1lrNl9UWo5PykdwN3j_ByJ9tiDVgrHUmuLXV3THju7XluPlQ5B-c7nZQx0zqMqYnihFSKeUuZwIL0KIPAEwVZpCg0WBOgHIaSDybuuKw5sAUQ4W9SuVTNXZ1DEOB7fRAE6eidRPMxUNS9sAcOEWohhe3ZYCQO0tNVM5asn3YUQBMHlxsu317YydnM4AS82Y61eu7Vr-nnf-lIpTEco00U_LL9dcb4Q"
    }
  ]
}
  • Copiez l'URL vers votre exploit et l'ajouter dans le header du JWT dans un paramètre "jku"

  • Remplacer le "kid" par celui dans l'exploit

  • Remplacer votre nom d'utilisateur par celui de votre victime

  • Cliquez sur "Sign" et sélectionnez la clé RSA utilisée pour l'exploit

  • Vérifiez que l'option "Don't modify header" est cochée puis cliquez sur "OK"

Vous devriez à la fin avoir un JWT qui ressemble à ceci:

{
    "kid": "daf86875-f562-4b2d-9a62-0f13f8ed77d2",
    "alg": "RS256"
    "jku": "https://evil.com/exploit"
}

Payload

{
    "username": "<target_username>",
    ...
}
  • Finalement, envoyez la requête et constatez que vous êtes connecté en tant que <target_username>

Contournement d'authentification via manipulation de paramètre kid

Prérequis: Extension JWT Editor de Burp Suite

Etapes:

  • Allez dans l'onglet JWK Editor Keys

  • Cliquez sur "New Symmetric Key" > "Generate"

  • Modifiez le paramètre "k" par un byte null encodé en base64 (signature nulle)

{
    "kty": "oct",
    "kid": "86d1d9cb-1284-48fa-b29f-bdeeba2a6814",
    "k": "AA=="
}
  • Interceptez la requête voulu

  • Allez dans l'onglet "JSON Web Token"

  • Remplacer le paramètre "kid" par un path traversal (vers dev/null afin d'ignorer le "kid"

Exemple:

{
    "kid": "../../../../../../../dev/null",
    "alg": "HS256"
}
  • Modifiez votre nom d'utilisateur par celui de votre cible

  • Cliquez sur "Sign", sélectionnez la clé symétrique généré précédemment, vérifiez que l'option "Don't modify" header est cochée puis cliquez sur "OK"

  • Finalement, envoyez la requête et constatez que vous êtes connecté au compte de votre cible

Notez que si le serveur stock ses clés de vérification dans une base de données, le paramètre "kid" peut potentiellement devenir un vecteur d'attaque par injection SQL

Autres vecteurs d'attaque

  • Le paramètre cty (Content Type) est parfois utilisé pour déclarer un type de média pour le contenu dans la charge utile JWT. Ceci est généralement omis de l'en-tête, mais la bibliothèque d'analyse sous-jacente peut le prendre en charge de toute façon. Si vous avez trouvé un moyen de contourner la vérification de signature, vous pouvez essayer d'injecter un en-tête cty pour changer le type de contenu en text/xmlou application/x-java-serialized-object, ce qui peut potentiellement activer de nouveaux vecteurs pour les attaques XXE ou de désérialisation.

  • x5c(Chaîne de certificats X.509) - Parfois utilisé pour transmettre le certificat de clé publique X.509 ou la chaîne de certificats de la clé utilisée pour signer numériquement le JWT. Ce paramètre d'en-tête peut être utilisé pour injecter des certificats auto-signés, similaires aux attaques par injection d'en-tête jwk vue précédemment. Ressources:

Attaques par confusion d'algorithme

Etapes généralement suivies:

  • Obtenir la clé publique du serveur

  • Convertir la clé dans un format approprié

  • Créer un JWT malveillant en manipulant le payload et en changeant l'algorithme de chiffrement en HS256

  • Signer le jeton en HS256 avec la clé publique comme secret

Les serveurs exposent parfois leurs clés publiques en tant qu'objets JSON Web Key (JWK) via un point de terminaison standard mappé sur /jwks.jsonou /.well-known/jwks.json, par exemple. Ceux-ci peuvent être stockés dans un tableau de JWK appelé keys. C'est ce qu'on appelle un ensemble JWK.

Pour que l'attaque fonctionne, la version de la clé que vous utilisez pour signer le JWT doit être identique à la copie locale du serveur. En plus d'être dans le même format, chaque octet doit correspondre, y compris tous les caractères non imprimables.

Exemple pour une clé au format X.509 PEM:

Etapes:

  • Trouvez la clé publique du serveur (via l'endpoint jwks.json par exemple)

  • Copiez l'objet jwk dans le tableau "keys"

{
    "kty":"RSA",
    "e":"AQAB",
    "use":"sig",
    "kid":"013acf5d-65af-4aa8-8527-898bac386146",
    "alg":"RS256",
    "n":"z5YvN4498LC-kwchA9Kzp60DOzIS3a3ckOKGE47YV9xPiw-msN5xeJHiG3-F-A9as_ioRFZGp4YZ7aCU5kGz_ILLPBq7ePKmvJ8-rCL2jtKHASG-sjL1qGE0ItgIbgNnhEGtHPDpc_Cd9c9OzzhM3VNNqRdVi5WRBttxBzAZj8iJASQTelOcLY4Ve6bIGg3qos-DUAqke5m9MVaxIPg8IzDy8HsWk2-olzTKB9y0xkIb-a3l9j62yIWu6qBT1ZzlFXLa0P4oOQi-LJ1MS-Z7k87VyltIQlbFCQUA67OBCfiQlhqsr_ibXkYJwAshSt0lMifXDGb2tt9K4AcOJhgsnQ"
}
  • Allez dans l'onglet "JWK Editor Keys"

  • Cliquez sur "New RSA Key" > Collez l'objet JWK dans le champ "Key"

  • Cliquez sur "OK" puis faites un clic droit sur la clé puis sélectionnez "Copy Public Key as PEM"

  • Allez dans l'onglet "Decoder" puis encodez la clé publique PEM en base64

  • Copiez le résultat puis retournez dans l'onglet "JWT Editor Key"

  • Cliquez sur "New Symmetric Key" > "Generate"

  • Echangez le contenu du paramètre "k" par la clé PEM encodé

  • Cliquez sur "OK"

  • Interceptez la requête voulu

  • Allez dans l'onglet "JSON Web Token"

  • Modifiez le paramètre "alg" du header en "HS256" si ce n'est pas déjà le cas

  • Echangez votre nom d'utilisateur par celui de votre cible

  • Signez votre JWT avec la clé symétrique générée précédemment (en vérifiant que l'option "Don't modify header" est cochée

  • Enfin, envoyez la requête et remarquez que vous êtes connecté au compte de votre cible

Dans le cas où il vous serait trop difficile de trouver la clé publique du serveur, il existe des outils permettant de la bruteforce.

ressource: https://github.com/silentsignal/rsa_sign2n

Dernière mise à jour