In Nov. 2020, Balsn was invited to participate in WCTF - a CTF event that only invited 10 world’s best CTF teams.
The most special part of this event is that each team needs to design 2 challenges for the other teams.
thymeleaf is a windows challenge designed by r3kapig.
- Type: Web
- Solved: 5/9
- Author: r3kapig
In the beginning, we found several pages like
/v2/api-docs by dirsearch.
However, the APIs found in
/swagger-ui.html could not be used in terms of the lack of permission.
After checking, I noticed that the authentication is based on JWT in cookie.
JSON Web Token is a signed message to maintain the integrity of the message. That is to say, we trust the message is correct based on the signature of JWT.
Because the content of JWT is just encoded plaintext, we can see the following message after decoding :
Generally, I would not like to try to brute force in an international CTF competition. However, we have no more clue, which forced me to try all the tricks about JWT.
In Founding and Trials, I'd like to share some common JWT tricks.
After brute force, we retrieved the secret of the JWT (
Therefore, we can sign all the content we give and access this website with proper permission.
However, for most of the APIs, we can do nothing except to the
DELETE /auth/user/someone with special behavior.
To be more specific, the server would render the path in the error page when we send the following request:
curl --cookie 'SESSION=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYWRtaW4iLCJpc3MiOiJYWC1NYW5hZ2VyIiwiaWF0IjoxNjA1NzQ5MTAwfQ.Yihr_zCEo90TPRsCa_yzkt8w_YIE1j4D4hkGdSl-xcA' 'http://126.96.36.199:10001/auth/user/admin3' -X DELETE
From this behavior, we learned that we need to reach RCE by SSTI.
After furthermore survey and examination, we found that the server is based on the thymeleaf (same as the name of this challenge).
With the following request, we can reach a simple SSTI.
DELETE /auth/user/__$%7bT(java.lang.Runtime).getRuntime().availableProcessors()%7d__::..x HTTP/1.1
The response would be like
Error resolving template [auth/user/8] .
The next step is to craft a payload without
(0).toString().charAt(0).toChars(105)%5b0%5d.toString() => 'I', we can create strings with no
Until now, we can reach RCE on the server.
After we can RCE on the server, we didn't obtain the flag immediately. The problem was that the environment was on Windows rather than Linux, and it took a lot of time to check and craft our payload.
We took almost 2 hours in this step and missed the first blood QQQ.
JWT is JSON Web Token. It uses a signature to make sure about the integrity of data. Commonly, people use JWT to reach Authentication.
JWT can resolve the sharing problem between multiple backend servers and decrease the cost of storing data on the server-side.
A JWT contains 3 parts:
payload: records the data itself
signed: the signature of both of the above data
Here are some common JWT attacks:
It just keep trying the possible keys. Though it is not a fancy attack, JWT is a friendly authentication for brute force.
Because a server just resigns and compare with the received signature, we can reach forgery the JWT via alternating the
algoand making sure that we can sign a valid
signed. It is noticeable that the
algowe assigned should be supported by the server.
- none (CVE-2015-9235): with
"algo": "none", we don't need any
- RS256 $\to$ HS256 (CVE-2016-10555): alternating the asymmetric algorithm to symmetric one, we can sign the
signedby the public key we have already known.
- none (CVE-2015-9235): with
JWKS Injection (CVE-2018-0114):
Some libraries can accept the public key from a client. As a result, we can insert a public key into
payloadand sign it with the corresponding private key.
Null Signature Attack (CVE-2020-28042)
Exploiting the Logic Flaws, when the
signedis null, it could bypass the validation.
If the server does not properly deal with the
kid, it might conduct read files or even SQLi, cmdi attacks.
headerto a URL that directs to our crafted JWKS file, the server might use the assigned key in JWKS file to validate.