← 返回 Day 163 正文

Day 163 · 练习与清单

Day 163 完成清单 · 安全审计工具箱(二):SQLi 检测 + XSS 检测

Phase 10 — 网络安全开发 · 阶段项目 Day 162–165 的第 2 天

⚠️ 实验只跑在本机回环靶标(code/vuln_core.py 的 LabVulnHTTP)。 只对自己拥有或已获书面授权的目标做检测;只发 GET;不取数、不绕过。


✅ 一、完成清单(照着打勾)

概念与原理(读 README.md)

代码与实测(在 code/ 下跑)

工程习惯


📝 二、基础练习题(3 道)

练习 1:读懂探针表(观察题)

运行 python3 01-sqli-detect.py,把 /product 与 /echo 的输出抄下来,回答:

  1. /product 的 error 探针返回的状态码是多少?检测器凭什么下结论?
  2. /echo 的 baseline/error/true/false 四个长度分别是多少? 其中"布尔差分不成立"是因为哪一条条件没满足(①②③)?
  3. 如果把 /echo 的输出给一个"只比长度"的检测器,它会得出什么错误结论?

验收标准:能用一句话说清"长度变化 ≠ 注入"。

练习 2:给检测器加一个探针并解释代价

在 vuln_core.py 的 detect_sqli() 里,把探针计划临时改成 5 个 (加一个 probe: 原值 OR 1=1),然后回答:

  1. 为什么 MAX_PROBES_PER_PARAM = 4 会让这个改动直接抛异常而不是静默多加一次请求?
  2. 把上限改成 5 让它能跑,观察 /safe-product 的结论会不会变。为什么?
  3. 讨论:如果一个真实工具想用 20 个探针,应该在哪里做补偿(限速?授权记录?报告?)

验收标准:能说出"硬闸门 vs 静默跳过"的设计差异,并明确它属于授权边界而非性能问题。

练习 3:上下文判定的手算

靶标 /profile?name=ops 的响应片段是:

html
<form><input name='fullname' value="【探针】"><button>保存</button></form>
  1. 手工执行 classify_context() 的三步判断(注释 → 脚本块 → 标签内), 写出每一步的 rfind 比较结果。
  2. 为什么它判成 attr_quoted_double 而不是 attr_unquoted?
  3. 如果响应写成 <input name='fullname' value='【探针】'>(单引号属性), 结论会变成什么?严重度会变吗?

验收标准:能画出"标记左边最近的未闭合结构"这张图。


🚀 三、进阶挑战题(2 道)

挑战 1:消灭"重复内容型"假阳性

背景:现在的 boolean_based 判据要求 true 贴近 baseline、 false 偏离 baseline。请构造一个会骗过它的假想端点:

然后给出至少两种改进方案,并比较代价:

方案 做法 代价 / 新风险
A 多次采样取长度分布(去掉 1 次采样的噪声) 请求数 ×N,撞上授权上限
B 换不变量:比较结构指纹(如 DOM 节点数、去空白后的文本长度) 需要解析 HTML,复杂度和误判面上升
C 你的方案 ?

验收标准:能说清"提高检出率"与"降低误报率"在这类工具里为什么天然对立。

挑战 2:把"覆盖完整性"做成可执行的门禁

当前 coverage 只统计 throttled / errors。请扩展它,使其能回答:

  1. 哪些具体目标没有取得结论?(列出 url + param)
  2. 给一个 --require-coverage 100 的 CLI 选项:只要有任何目标未取得结论, 就退出码 4 并在报告里单开一节「未覆盖清单」。
  3. 思考:这算不算"检测工具的正确用法"?如果一个工具永远无法 100% 覆盖, CI 里应该设置成 --require-coverage 多少?(提示:结合"无法覆盖的原因"分类讨论: 限速 / 网络 / 门禁拒绝,哪一种应该阻断流水线?)

验收标准:产出一份"未覆盖清单" Markdown,且退出码语义与 README §2.7 表格一致。


🔍 四、自检命令(一键跑完)

bash
cd days/day-163-安全审计工具箱-part2/code

python3 vuln_core.py --self-test && \
python3 01-sqli-detect.py > /tmp/d163-01.log 2>&1 && \
python3 02-xss-detect.py > /tmp/d163-02.log 2>&1 && \
python3 03-vuln-scan-cli.py --lab > /tmp/d163-03.log 2>&1; echo "exit=$?"

grep -c "error_based" /tmp/d163-01.log
grep -c "script_block" /tmp/d163-02.log
ls out/

预期:--self-test 输出 SELF-TEST OK;最后一条命令的 exit=3; out/ 下至少有 day163-lab-report.{json,md}。


📌 五、今日关键结论(背下来)

1. 报错特征是强证据(自证),布尔差分是弱证据(必须锚定 baseline)。
2. 长度变化 ≠ 注入:/echo 陷阱专治"只比长度"。
3. XSS 判定是四层:反射 → 转义 → 上下文 → 缓解措施,少一层就失真。
4. 探针不是载荷:检测只需证明"危险字符原样进入 HTML",无需真的执行。
5. 缺缓解措施头是事实,不是结论("缺 CSP" ≠ "有 XSS")。
6. 越界 = 退出码 2(不重试);没测完 = 退出码 4(不能当通过)。
7. 优先级 = 严重度 × 置信度:两个维度独立,不能压成一维。
8. 边界是用来让程序停下来的(硬闸门抛异常),不是用来"温柔提醒"的。