WCTF 2020 - thymeleaf


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 /login, /swagger-ui.html, /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 :

"role": "guest",
"iss": "XX-Manager",
"iat": 1605749100

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 (admin). 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' '' -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
User-Agent: curl/7.69.1
Accept: */*
Cookie: SESSION=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYWRtaW4iLCJpc3MiOiJYWC1NYW5hZ2VyIiwiaWF0IjoxNjA1NzQ5MTAwfQ.Yihr_zCEo90TPRsCa_yzkt8w_YIE1j4D4hkGdSl-xcA
Connection: close

The response would be like Error resolving template [auth/user/8] .

The next step is to craft a payload without " and '. With payload (0).toString().charAt(0).toChars(105)%5b0%5d.toString() => 'I', we can create strings with no " or ' . Until now, we can reach RCE on the server.

RCE on Windows

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.

Founding and Trials

JWT attacks

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:

  1. header: records type and algo
  2. payload: records the data itself
  3. signed: the signature of both of the above data

Here are some common JWT attacks:

  1. Brute Force

    It just keep trying the possible keys. Though it is not a fancy attack, JWT is a friendly authentication for brute force.

  2. alter the algo

    Because a server just resigns and compare with the received signature, we can reach forgery the JWT via alternating the algo and making sure that we can sign a valid signed. It is noticeable that the algo we assigned should be supported by the server.

    1. none (CVE-2015-9235): with "algo": "none", we don't need any signed.
    2. RS256 $\to$ HS256 (CVE-2016-10555): alternating the asymmetric algorithm to symmetric one, we can sign the signed by the public key we have already known.
  3. 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 payload and sign it with the corresponding private key.

  4. Null Signature Attack (CVE-2020-28042)

    Exploiting the Logic Flaws, when the signed  is null, it could bypass the validation.

  5. "kid" Injection

    If the server does not properly deal with the kid, it might conduct read files or even SQLi, cmdi attacks.

  6. JWKS Spoofing

    Editing the jku in the header to a URL that directs to our crafted JWKS file, the server might use the assigned key in JWKS file to validate.


© 2021 RB's Page All Rights Reserved.
Theme by hiero