Rating: 2.0

## Flag jokes, WEB 200 pti
#### Author: p4w

### TL;DR
In this challenge we have to exploit a __JWKS Spoofing__ vulnerability. This vulnerability exists if the application __trust an arbitrary url__ to retrieve the __public key__ to verify the cookie signature. An attacker can host his own public key on his malicious server in order to modify and sign the cookie with his key-pair.

### Token analysis

* The challenge let us login with any username we want, except from __admin__, and the goal is to become __admin__.
* The login phase is simple we send the username we want and the application respond with a signed jwt.
* Analysis of the jwt-cookie:

* Token analysis
* As we can notice we have 3 elements into the json part of the jwt-header and you can find the details at this link https://tools.ietf.org/id/draft-ietf-jose-json-web-signature-01.html#rfc.section.4

![alt cert decoder](./screen/jws_spec.png)

* To summarize, the alg header parameter specify the algorithm used by the web-application to sign the cookie. The kid header parameter is used to identify a specific key in a list of keys. The jku header parameter is used to point to an URL which contains a set of __json encoded public keys__.

* Let's see if we can retrieve the remote jwks.json file pointed by the token we have
![alt cert decoder](./screen/retrive_jwks_file.png)

### Exploiting the vuln

* The general idea should be to tamper the jkw to point to our server hosting our jwks.json file with our lists of keys.

* Generate RSA key-pair with openssl:
* with this command we can generate the RSA private key:

$openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048  * with this command we can extract the public certificate associated to the RSA private key previously created: $ openssl rsa -pubout -in private_key.pem -out public_key.pem

* Now we should have both __PUBLIC__ and __PRIVATE__ certificate in our current folder and we need to extract the n value. To do that I used an online service:

![alt cert decoder](./screen/extract_public_key_values.png)

* Since the values for the public key contained in the jwks.json shold be in base64, then we need to convert the n from hex to base64(raw-hex-bytes). To do that we can use burp-proxy:

![alt n decode](./screen/encode_n_in_b64.png)

* Create our jwks.json file. To do that we can just use the original one and replace the value of __n__ with the value associated with our RSA-key:


\$ cat jwks.json
{
"keys": [
{
"e": "AQAB",
"kid": "sqcE1a9gj9p08zNMR1MWbLLvuaPyUeJEsClBhy7Q4Jc",
"kty": "RSA",
"n": "wed4pVV95ZD+G5s+Ahlmb96zURRK70efNvduoOPIaaFmmPRBgSLSNCEF//VntFI2l72t8IOXQQ7sS/0JbnpzjHJ4Duo6KPyE9U/Ros1z6m46w/Ncw0xMcKkLTJjswxH3Ql4kIaueN988gppGbheEvWCazbQfgR8UD54zoGd6aqO71ni3Mp81ypoU1zjq7r4OfdX4iCv/ICxC4H9RFIFDX/4AnFa6CNmOCOhP2fKarFV3iWYEPtqOsoJx2tu6YP7ecv70DVfVzR9Zd4JbQuLkNtbo+ccCFTYQp2FYFkKveh+3LbfnWY2cIQdqPGG6i57B3qQkYF2FvvEzZaIFXjbiAQ=="
}
]
}

* Now we need to modify the __jku__ value of the jwt-header to point to our server where we hosted the jwks.json file, and modify the payload data to become admin. After we can sign the cookie with our hosted RSA key-pair and to do that I used the https://jwt.io service:

![alt cert decoder](./screen/sign_jwt.png)

* Send the request to the challenge web application and get the __flag__

![alt cert decoder](./screen/get_flag.png)

### reference:
* https://github.com/ticarpi/jwt_tool/wiki/Known-Exploits-and-Attacks
* https://tools.ietf.org/id/draft-ietf-jose-json-web-signature-01.html#rfc.section.4
* https://book.hacktricks.xyz/pentesting-web/hacking-jwt-json-web-tokens
* https://jwt.io/

Original writeup (https://github.com/beerpwn/ctf/tree/master/2020/NahamCon_CTF/web/Flag_Jokes).