Preparing for OSCP | Sharing Practical Labs & Real-World Attack Analysis
Step 1: Reconnaissance
Nmap Scan
nmap -sCV -A โ min-rate 1000 192.168.224.234

Three ports were found:
โข 22/tcp โ OpenSSH 8.2p1 Ubuntu
โข 3000/tcp โ Uvicorn HTTP server (BentoML Runner Server)
โข 8888/tcp โ Uvicorn HTTP server (BentoML Prediction Service)
Port 8888 title revealed BentoML Prediction Service. Accessing the web interface confirmed BentoML version 1.4.6 which is vulnerable to CVE-2025โ32375 โ an unauthenticated RCE via insecure pickle deserialization in the runner server.

Step 2: Vulnerability Analysis โ CVE-2025โ32375
About the Vulnerability
CVE-2025โ32375 is a critical (CVSS 9.8) unauthenticated remote code execution vulnerability in BentoML versions >= 1.0.0a1 and < 1.4.8. The runner server handles POST requests with specific headers and passes the request body directly to pickle.loads() without any validation or sanitization.
By crafting a malicious pickle payload and sending it with specific headers (args-number, Payload-Container, Payload-Meta, Batch-Size), an attacker can trigger arbitrary code execution on the server without any authentication.
Vulnerable Code
# src/bentoml/_internal/runner/container.py

Required Headers

Step 3: Exploitation
Step 3.1 โ Start Netcat Listener
nc -lvnp 4444

Step 3.2 โ Create Exploit
cat > exploit.py << 'EOF'

Step 3.3 โ Run Exploit
python3 exploit.py

Step 3.4 โ Shell Received

BentoML runner server was running as root. The pickle deserialization executed our FIFO reverse shell payload directly, giving us an immediate root shell with no privilege escalation required.
Step 4: Capture Flag
cat /root/proof.txt

Key Learnings
โข CVE-2025โ32375 โ BentoML's runner server passes HTTP request body directly to pickle.loads() without any validation. Crafting a malicious pickle payload with __reduce__ triggers arbitrary OS command execution.
โข Pickle Deserialization โ Python's pickle module is inherently unsafe for deserializing untrusted data. The __reduce__ method allows embedding arbitrary code that runs automatically during deserialization. Never use pickle.loads() on untrusted input.
โข No Authentication โ The runner server endpoint required no authentication, making it exploitable by any network-accessible attacker. ML serving frameworks should never be exposed to untrusted networks without authentication.
โข Root Process โ BentoML runner server was running as root, turning a network RCE directly into full system compromise. Services should always run with least privilege โ never as root.
โข Service Identification โ Uvicorn on ports 3000 and 8888 immediately suggested a Python web application. BentoML title was visible without authentication, leaking exact version information useful for targeted exploitation.