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

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

配套仓库: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.py 和 playground/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.py、A6/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...

相关推荐
数据技术说1 小时前
在 KES AI 数据库上搭一条 NL2SQL 链路:语义、召回、权限各放哪
人工智能·sql·代码规范
IT规划师2 小时前
Agent 总返工? Google 工程师把工程实践写成了技能库
ai编程·代码规范
疯华整猫1 天前
一个 == 让优惠券发错:编码规范在防什么,以及我为什么在 CR 里破过阿里的规矩
代码规范·全栈·阿里巴巴
非优秀程序员2 天前
第02章 杭电的英语老师与一台服务器|《互联网产品恩仇录》
数据库·node.js·代码规范
这个DBA有点耶2 天前
函数索引的“完全一致”有多苛刻:写法、字符集、类型,差一处就失效
数据库·mysql·代码规范
这个DBA有点耶3 天前
数据同步的三个工程底线:DDL同步、断点续传、一致性校验——开源CDC的边界与KFS的路径
数据库·dba·代码规范
这个DBA有点耶3 天前
MySQL 8.0不可见索引:删索引怕出事,不删又拖慢写入——中间态怎么用?
数据库·mysql·代码规范
miss3 天前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
这个DBA有点耶4 天前
MySQL 8.0直方图:统计信息升级了,执行计划为什么还是选错?
数据库·mysql·代码规范
十二同学啊10 天前
Go 工程化详解:项目结构、代码规范、测试体系与 CI/CD 实践
ci/cd·golang·代码规范