CTF Writeup: KnightShop (460 Points) — The Hidden Parameter That Gave Me $1000+ Credit!
Challenge: KnightShop (460 Points) | Type: CTF/Web/Logic Flaw | Author: TareqAhamed (0xt4req)
Assalamu Alaikum everyone! I recently solved a fun web/API CTF challenge called KnightShop from the "CipherSprint Powered by Knight Squad" competition. The challenge description was short but tricky: "Buy a product & I'll give you a flag."
Starting the challenge with full focus!
The Problem: Not Enough Money/Credit
The KnightShop is an online store. After registering, every new account got only $100 store credit. However, the shop only had four products, and every single one was priced higher than or equal to $200. The cheapest product was $200.
Since you need to buy a product to get the flag, but your starting credit isn't enough, it means there must be a way to manipulate either the product price or your starting credit.
Step 1: Checking JWT and Initial Attack Vectors
I started by analyzing the authentication. The site was using a JWT token for authentication. I copied my token and decoded it with the JWT editor in Burp Suite Pro. It looked like this:
{"email":"test@empty.com","user_id":3025}
I suspected a misconfiguration, so I tried common JWT attacks:
- Changing the `user_id` to 1 (hoping for admin access)
- Changing the `email` to an admin email
- Attempting to remove the signature part
Result: None of the JWT attacks worked. The token was implemented securely.
Step 2: Cart and Price Manipulation Attempts
I moved on to testing the core business logic of a shopping site, specifically the "Add Item to Cart" function.
A. Quantity and Integer Overflow
I tried adding a huge number of items, hoping to cause an integer overflow that would reset the price to $0. I've seen similar logic flaws in this PortSwigger Academy lab, but in this case, the large quantities were handled correctly.
B. Direct Price Manipulation
I looked at the request for adding a product (Product ID 4, priced at $200.0) to the cart:
GET /add-to-cart/4?price=200.0
I manually tried to reduce the price parameter:
GET /add-to-cart/4?price=100.0
Result: This didn't work. The server performed a backend validation, confirming the product's actual price.
C. Quantity Parameter Guessing
Since there was no explicit quantity parameter, I tried adding custom parameters like `qty=` and `quantity=` so that I could manipulate the quantity value, such as using a negative or a floating-point number. I tested almost everything possible on a shopping site to get a product at a reduced price. Although I didn't try anything related to coupon codes because there was no indication of using any coupon codes in this shop. Still I couldn't get them to work either.
Feeling stuck after my initial ideas failed.
Step 3: The Lightbulb Moment — Parameter Guessing!
I decided to stop messing with the cart and go back to the source of the problem: the $100 credit. I realized I had only tried common parameter names like `credit=` or `balance=` when trying to manipulate credit during checkout or registration.
My thought process was: *What if the developers used a less obvious, but still logical, variable name in the backend for the initial credit during registration?*
I decided to use a smarter approach: asking an LLM (like ChatGPT) for suggestions on common variable names for "shop credit" in a backend environment. I got a list including: `store_credit`, `initial_credit`, `wallet_balance`, etc.
I immediately went back to the `/register` endpoint request and tried the first guess: `store_credit=`.
POST /register HTTP/1.1
Host: 160.187.130.170:9052
Content-Length: 65
email=empty%40empty.com&password=Str0nGP@$$w0rD&store_credit=1000
Success! This is a classic Mass Assignment or Parameter Pollution vulnerability. The registration handler was unexpectedly accepting the `store_credit` parameter from the user input and using it to set the new account's balance in the database, overriding the default $100.
The sweet feeling of a successful exploit!
Final Step: Getting the Flag
With my new, self-assigned $1000 credit, I could easily buy any product in the shop. I quickly navigated to the product page, added the item to my cart, and proceeded to checkout. The purchase was successful, and a "Congratulations!" message appeared with the flag.
The Flag: CS{Fl4g_HeR3} The actual flag is secret, you have to try it yourself! 😉
Takeaway for Developers and Researchers
This challenge is an excellent reminder for developers to be extremely careful with how input parameters are handled, especially during sensitive operations like user registration or account creation. Always use a strict whitelist approach for expected parameters, discarding any extra ones sent by the client. For us researchers, remember: if the front door is locked, check the hidden back window (i.e., try guessing those unusual but logical internal parameters!).
Thank you for reading this write-up!
Regards, @emptymahbob