我的漏洞扫描器,把被测项目的源码写坏了

我的漏洞扫描器,把被测项目的源码写坏了

配套仓库:github.com/mabupt/open... 感谢各位查看并提出意见,劳烦各位star。

先说结论

我给自己的 Python 漏洞检测流水线加了"动态验证"------在 Docker 沙箱里真实触发被测代码的漏洞, 用双轨证据(Sink 调用记录 + Canary 污点)判定告警真假。跑通那天很爽:靶场上 15 条告警被实证确认

第二天重跑,confirmed 从 15 掉到 2

排查了半天,原因不是模型、不是规则、也不是我以为的"镜像变弱了"------ 是我自己的扫描器把被测项目的源码写坏了

事故经过

被测靶场 pygoat 里有两个 lab,漏洞本身就是"把用户提交的内容写进源文件":

python 复制代码
# pygoat A9 lab(简化)------漏洞就是把用户输入写入 Python 源文件
def a9_lab(request):
    log_code = request.POST.get("log_code")
    with open("playground/A9/main.py", "w") as f:
        f.write(log_code)

动态验证的设计就是真实利用 这类漏洞:构造载荷 → 发请求 → 观察 Sink 是否被污染。 探针一跑,playground/A9/main.pyplayground/A6/utility.py 就被我自己的载荷覆盖成了空内容。

接下来的连锁反应很隐蔽:

  1. 被写坏的文件属于 introduction.apis 模块 → 导入失败;
  2. Django 的 URLconf 只剩 7 条路由,其余回调退化成占位对象;
  3. 所有 Django 路由返回 500 → 探针拿不到任何 Canary 污点证据;
  4. 结果:Django 系候选 16 条全部 app_unreachable / retry_poc

最讽刺的地方:这不是"检测失败",而是"检测成功得过了头"------工具确实证明了漏洞可利用, 代价是把被测代码本身当作攻击目标写坏了。

修复:副本挂载

根因很明确:探针是直接 bind mount 宿主工程目录进容器的,写操作直达真实文件。

修复方式是把"被测工程"以副本 形式挂进容器,并且保持相同的容器内路径

python 复制代码
copy_dir = self._protected_copy(target)      # output/sandbox/protect_<hash>/
mounts.append(Mount("/workspace/<rel>", str(copy_dir), type="bind"))

有两个"顺手就能做错"的细节:

  • 副本创建失败时不能回退为挂载原目录 。我一开始的回退逻辑是 except: continue, 结果是"隔离静默失效"------探针照样写宿主。现在改为:副本建不出来就直接放弃这次探针, 宁可少做一次动态验证,也不冒险写坏用户工程。
  • 仓库外的目标同样要隔离 。我用 relative_to(workspace_root) 判断路径, 目标不在仓库内时抛 ValueError,而那个异常被 except: continue 吞掉了------ 也就是说,用户扫描自己仓库外的项目时,隔离是完全失效的 。现在统一约定: 仓库内挂 /workspace/<rel>,仓库外挂 /target,副本挂载逻辑三方共享。

验证方式很直接:跑完后看副本目录------A9/main.pyA6/utility.py 确实变成了 0 字节, 宿主工程的文件完好无损。

顺带修复:换环境即踩的三类坑

这次事故让我意识到:"在我机器上能跑"和"在别人机器上能跑"是两件事。于是做了一轮针对性复查:

  1. 换项目 → 路径约定三方不一致 :探针按宿主绝对路径找目标、沙箱挂 /workspace、 供给流程挂 /proj,三处各搞各的。统一为一套路径换算函数。
  2. 换环境 → 仓库外目标无隔离:见上一条,同一个根因。
  3. 换解释器 → 附加产物不应该让主流程陪葬 :用 python -m venv 建一个 零第三方依赖 的环境跑全流程------发现缺 jinja2 时,JSON 报告已经写好了, 却因为 HTML 渲染抛异常导致整个流程 exit 1。现在 HTML 降级为"只出 JSON + 告警", 并做了更彻底的验证:42 个模块全部可导入(第三方依赖均为延迟导入), Semgrep / CodeQL / pip-audit 走 PATH 照常工作, Qdrant / fastembed / Docker 缺失时逐级降级,全流程 exit 0

值得记下来的四条经验

  1. 动态验证工具必须假定"被测代码会被破坏"。因为触发漏洞的后果就是破坏------ 哪怕破坏对象是它自己。隔离不是可选项。
  2. except: continue 是隔离类代码里最危险的写法。它把"隔离失败"变成了"静默不隔离", 比直接报错危险得多。
  3. "降级"要覆盖到最外层。附加产物(HTML 报告)失败不该让主产物(JSON)和整个流程陪葬。
  4. 换环境测试比加功能更值得投入。上面三个坑,没有一个能在"我自己机器上跑一遍"时暴露。

相关的完整加固记录见仓库 docs/HARDENING.md。 项目地址:github.com/mabupt/open...

相关推荐
事圆则缓3 小时前
遗留项目改造实战指南:从可读性、代码质量到性能和 AI 约束
android·ai·代码规范
乱码三千8 小时前
开发了一套AI智能体协作知识体系
人工智能·架构·代码规范
梦梦代码精3 天前
《回收租赁系统技术选型避坑指南:业务闭环与二开自由度详解》
开发语言·低代码·docker·开源·代码规范
这个DBA有点耶3 天前
临时表从4.7秒到0.12秒:不是所有Using temporary都需要优化
数据库·mysql·代码规范
泛联新安3 天前
“天神”空降:泛联新安受邀参加第八届“纵横”网络空间创新论坛
网络安全·自动化·代码规范·漏洞挖掘·代码安全·代码漏洞扫描·ai+可信开发
用户970161501683 天前
浏览器切到后台后,AI 给我的代码就失效了:我拿 3 个模型测了 6 个定时器坑
前端·代码规范
RunProof可证工程4 天前
AI 写的登录接口能跑,上线前我却查出 SQL 注入写法
sql·代码规范
咖啡八杯4 天前
实体基类设计:BaseEntity 公共字段抽取与 TreeEntity 树形继承
java·架构·代码规范
这个DBA有点耶6 天前
MySQL 8.0执行计划分析利器:EXPLAIN ANALYZE到底比EXPLAIN强在哪?
数据库·mysql·代码规范