0%

BreakingBankChallengeWrite-Up(Web)-HTBUniversityCTF2024

Omar Mohamed
Thanks for sharing!

بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

Breaking Bank Challenge Write-Up (Web) - HTB University CTF 2024
Hello there! Today, I'm going to walk you through solving the Breaking Bank challenge from HTB University CTF 2024.
Before we get started, if you want to try the challenge, you can find it here.

Content

Let's dive in!

Challenge Overview

Challenge Overview

Initial Recon

First thing I did was check out the website. We got a login and register form:
Login Page
Made my account and logged in. We have a cryptocurrency platform with Market Overview and a portfolio which my balance is set to zero:
Dashboard Overview
Portfolio View
We also got another 2 interesting tabs: friends and Transactions.

Source Code Review

The source code was quite big, so I took it in reverse - how can I get to the flag?
Searched for flag.txt in VS code and found this:
We see that we can get the flag if we drained CLCR coin (set it to 0) of the user with this email: financial-controller@frontier-board.htb
So how can we do that?
Remember we have a transaction page, so simply we can transfer all the amount of this coin to another user, and we get it
In /src/pages/Transaction.tsx, found this endpoint: /api/crypto/transaction
Notice it needs a JWT token? Let's check our token in localStorage:
JWT Token in LocalStorage
Passing it to jwt.io, we got:
Header:
Body:
We notice this file: http://127.0.0.1:1337/.well-known/jwks.json which gets us this:
Quick Note: JWKS (JSON Web Key Sets) is a set of keys containing the public keys used to verify any JWT issued by an authorization server. The jku (JWK Set URL) header parameter is used to retrieve these keys.
Let's keep it for later and understand the logic first

Verification Function Analysis

(where the good stuff begins)
searching in vscode for verify, we got verifyToken function in /challenge/server/services/jwksService.js
The functionis pretty basic but here are some parts which pop up:
here it checks if jku header starts with http://127.0.0.1:1337/
The kid must match the KEY_ID on the server, which we can easily get from our own token
Now for the interesting part: it gets some data from the link in jku header, which in our token was: http://127.0.0.1:1337/.well-known/jwks.json
Next, the function retrieves the jwk whose kid matches the server's, then passes it to the jwkToPem function to convert it into a PEM-formatted public key:
The jwkToPem function ensures the key is of type RSA, converts its components (n and e) to base64url, and creates a PEM public key using Node's crypto module.
This step is important because we'll use a similar approach to craft our own key later.
now lets's summer up what we have so far:
  1. Goal: Transfer all CLCR from financial-controller@frontier-board.htb to get the flag.
  2. JWT Validation: The server checks the jku URL and fetches a key (jwk) to verify tokens.
  3. Plan: Host a fake key on a controlled server, make the server fetch from it, and forge a token

First Lets make our hosted fake key

I made the following script, Let's take it bit by bit
  1. Key Generation:
    • Generates an RSA key pair (privateKey and publicKey) for signing and verifying tokens.
    • KEY_ID is a unique identifier for the key (you get it from your token)
  2. JWKS (JSON Web Key Set):
    • Converts the publicKey to a JWK (JSON Web Key) format.
    • Adds metadata (alg, use, kid)
  3. JWT (JSON Web Token):
    • Creates a token with a payload (email and iat).
    • Custom header includes:
      • kid: Matches the key ID (KEY_ID) (Make sure to put yours)
      • jku: URL pointing to the fake JWKS file.
    • Signs the token using the private key.
  4. Output:
    • Logs the forged JWT and JWKS to use in the attack.
If you tried this... it will not work, know why? Remeber the
it has to start with http://127.0.0.1:1337/
but how can we make it fetch from our server of it has to start with this??? Answer is open redirect
So a little of searching (Also these // TODO commenets made it easier to spot the right stuff) we find analytics.js file with this inside
This is a straight up redirection so that's how we are gonna make the server fetch our hosted key You can use ngrok, but I hosted mine on my website: https://h4ck.run/jwks.json The final url will look like this:
http://127.0.0.1:1337/api/analytics/redirect?url=https://h4ck.run/jwks.json/&ref=dummy
Notice the dummy ref is required in order to redirect
Note: This script generates its keys dynamically in each run, so make sure to use the right token with its right hosted key
Now since we finally got our token, lets try it out

Getting Access

Now with our forged token, let's check if it worked:
Portfolio After Token
Nice! Our portfolio value isn't zero anymore, which means we got in!

Getting the Flag

Made another account and added it as a friend to transfer the coins to. But when trying to transfer...
Burp Request
Still need to bypass the OTP. Looking at otpMiddleware.js:
It's using includes()!
If you send a dummy otp and see the request in burp, you can see the otp is sent in an array
burp
So simply make and array with all possible otps and you got it
["0001","0002","0003","0004","0005"..."9999"]
The command to generate it:
To copy it use:
Note: Put it in burp by deleting the existing array and putting yours. Don't put it directly in the input beacuse it will be handled as one string in this array, as you can see the otp was passed as a string
success
flag
And here is our flag!
Flag: HTB{rugg3d_pu11ed_c0nqu3r3d_d14m0nd_h4nd5_789dfb9e1ce0f5ca7741ba640da6ce29}

Achievement

I'm proud to share that our team ranked in the top 200 in this CTF! Here's the certificate of achievement:
HTB University CTF 2024 Certificate

Key Takeaways

This challenge had a bit of everything:
  1. JWT and JWKS stuff
  2. Open redirect vulnerability
  3. OTP bypass using array tricks
Really enjoyed solving this one! Hope you liked the write-up. See you in the next one!
psst.. you can buy me a coffee here 👀. thank you!

You might also like