跳转到内容

阶段 3 — 缓解

阶段 3 创建 CSD 缓解的前后对比证明。您先在无缓解措施的情况下重新运行攻击以建立基线,然后应用缓解措施,再次运行相同的攻击以证明 CSD 阻断了网络调用。在继续之前,阶段 2 必须已完成——所有 DET 检查均通过(PASS)。

步骤 1:确认无活跃缓解措施(基线)

Section titled “步骤 1:确认无活跃缓解措施(基线)”

在捕获”之前”快照之前,验证环境是否干净——不应有任何活跃的缓解措施。这确保基线攻击在没有任何 CSD 阻断的情况下运行。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq '{count: (.items | length)}'

如果数量不为 0,则存在来自先前运行的缓解措施。在继续之前删除每一条:

Terminal window
# 删除已缓解的域名(对每个域名重复执行)
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains/<domain-name>" \
| jq .

<domain-name> 替换为缓解该域名时使用的 metadata.name(例如 cdn.jsdelivr.netesm.shunpkg.comga.jspm.iohttpbin.orgjsonplaceholder.typicode.com)。如果 httpbin.org 清理后仍有残留项目,也请尝试删除 www.httpbin.org——某些先前的运行可能使用了该名称作为 metadata name。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{total_domains: .domain_summary.totalDomains, domains: [.domains_list[]? | {domain: .domain, category: .category}]}'
检查项预期状态
已缓解域名数量0(干净基线)为 0 则 PASS,大于 0 则需要清理
已检测域名数量> 0(阶段 2 检测结果存在)大于 0 则 PASS
数据外泄域名存在www.httpbin.orgjsonplaceholder.typicode.com至少出现一个则 PASS

无缓解措施活跃的情况下重新运行组合模拟,以捕获新鲜的基线。这是**“之前”快照**——证明在未应用 CSD 缓解时攻击成功。

具有浏览器自动化工具的 AI 助手使用与阶段 2 相同的 initScript(保存原生 fetch)以编程方式运行攻击模拟:

  1. 带 initScript 导航 — 首先导航至 about:blank 以确保干净的文档上下文(避免先前导航遗留的过期 initScript),然后使用阶段 2 initScript阶段 2 — AI 自动化执行 中的逐字代码)通过 navigate_page 导航至 http://$F5XC_DOMAINNAME/#/login。此 initScript 保存原生 setIntervalclearIntervalfetchconsole.log——此处原生 fetch 引用是正确的,因为没有活跃的缓解措施
  2. 关闭欢迎横幅 — 使用 Escapepress_key 关闭欢迎横幅。在后续访问中横幅可能不会出现(cookie 已持久化)。Cookie 同意对话框通过 Escape 键自动关闭
  3. 等待完成 — 等待 10 秒,让所有 CDN 脚本加载/错误回调和 fetch promise 解析完成
  4. 捕获证据 — 使用 list_console_messages 检查 [CSD Demo] Simulation complete 和 CDN 加载结果;使用 list_network_requestsscriptfetch 类型过滤,以验证 HTTP 状态码(200/201 表示成功)

没有浏览器自动化工具的操作人员使用与阶段 2 — 步骤 8:攻击模拟相同的流程手动运行模拟:

  1. 导航至 http://xF5XC_DOMAINNAMEx/#/login
  2. 在电子邮件和密码字段中输入虚拟凭据(不要提交)
  3. 打开开发者工具——按 F12 并切换至 Console 标签页
  4. 粘贴并运行触发检测中的组合检测脚本
  5. 观察控制台输出——所有 CDN 脚本应正常加载,数据外泄调用应以 200/201 响应成功返回
检查项预期(缓解前)状态
CDN 脚本注入所有 4 个脚本标签加载——出现 [Supply Chain] Loaded from 消息,网络标签显示 200PASS
www.httpbin.org 的数据外泄 fetch网络标签显示 200——数据已发送PASS
向 jsonplaceholder.typicode.com 的数据外泄 fetch网络标签显示 201——数据已发送PASS
控制台输出[CSD Demo] Simulation completePASS

对每个检测到的域名,向已缓解域名端点发送 POST 请求。阶段 2 模拟中的主要目标是 4 个 CDN 注入域名和任何检测到的数据外泄域名。

主要缓解目标(来自组合模拟脚本):

域名角色
cdn.jsdelivr.netCDN 脚本注入
esm.shCDN 脚本注入
unpkg.comCDN 脚本注入
ga.jspm.ioCDN 脚本注入
www.httpbin.org数据外泄端点
jsonplaceholder.typicode.com数据外泄端点

缓解一个域名(每个域名运行一次):

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"name": "cdn.jsdelivr.net",
"namespace": "xF5XC_NAMESPACEx"
},
"spec": {
"mitigated_domain": "cdn.jsdelivr.net"
}
}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .

对每个域名重复执行:

esm.sh
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"metadata":{"name":"esm.sh","namespace":"xF5XC_NAMESPACEx"},"spec":{"mitigated_domain":"esm.sh"}}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .
# unpkg.com
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"metadata":{"name":"unpkg.com","namespace":"xF5XC_NAMESPACEx"},"spec":{"mitigated_domain":"unpkg.com"}}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .
# ga.jspm.io
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"metadata":{"name":"ga.jspm.io","namespace":"xF5XC_NAMESPACEx"},"spec":{"mitigated_domain":"ga.jspm.io"}}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .
# httpbin.org — 使用 www.httpbin.org 作为 mitigated_domain(见下方说明)
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"metadata":{"name":"httpbin.org","namespace":"xF5XC_NAMESPACEx"},"spec":{"mitigated_domain":"www.httpbin.org"}}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .
# jsonplaceholder.typicode.com
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"metadata":{"name":"jsonplaceholder.typicode.com","namespace":"xF5XC_NAMESPACEx"},"spec":{"mitigated_domain":"jsonplaceholder.typicode.com"}}' \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq .

200 响应返回已创建的缓解域名对象。409 响应表示该域名已在缓解列表中——这是成功条件。

列出所有已缓解域名,并确认数量与刚刚提交的域名数量匹配:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq '{count: (.items | length)}'
检查项预期状态
已缓解域名数量6(与 POST 数量匹配)数量匹配则 PASS
步骤 3 的所有 POST 返回 200409每个域名均已接受PASS

如果数量低于预期,请重新运行步骤 3 中缺失域名的 POST 命令。

重新运行完全相同的组合模拟以捕获**“之后”快照**。模拟脚本完全相同——只有 CSD 的缓解状态发生了变化。来自已缓解域名的脚本加载现在被 CSD JavaScript 阻断(&lt;script&gt; 标签的 src 被清除为空字符串)。

具有浏览器自动化工具的 AI 助手使用相同的阶段 2 initScript阶段 2 — AI 自动化执行 中的逐字代码)以编程方式重新运行攻击模拟。initScript 保存原生 fetch 以避免 zone.js 错误——这不影响 CSD 缓解,因为 CSD 不拦截 fetch() 调用。

  1. 带 initScript 导航 — 使用带有 isolatedContextnew_page 获取干净的浏览器上下文(避免步骤 2 遗留的过期 initScript),然后导航至 about:blank,再使用阶段 2 initScript 导航至登录页面
  2. 关闭欢迎横幅 — 使用 Escapepress_key
  3. 等待完成 — 等待 10 秒让所有异步回调完成
  4. 捕获证据 — 使用 list_console_messages 检查 [CSD Demo] Simulation complete;使用 list_network_requestsscriptfetch 类型过滤,观察 CDN 脚本加载不存在(CSD 已清除脚本 src),而对数据外泄域名的 fetch 调用仍正常完成

没有浏览器自动化工具的操作人员使用与阶段 2 — 步骤 8:攻击模拟相同的流程手动重新运行模拟:

  1. 导航至 http://xF5XC_DOMAINNAMEx/#/login
  2. 在电子邮件和密码字段中输入虚拟凭据(不要提交)
  3. 打开开发者工具——按 F12 并切换至 Console 标签页
  4. 粘贴并运行触发检测中的组合检测脚本
  5. 观察控制台和网络输出——已缓解域名的 CDN 脚本 onloadonerror 回调不会触发(CSD 已将脚本 src 清除为空字符串,完全阻止了网络请求)。对数据外泄域名(www.httpbin.org、jsonplaceholder.typicode.com)的 Fetch 调用仍然完成,返回 200/201——CSD 缓解阻断脚本加载,而非 fetch/XHR 调用
检查项预期(缓解后)状态
CDN 脚本加载已阻断 — 脚本不出现在网络标签中(CSD 已将 src 清除为空字符串)PASS
CDN 脚本回调已缓解域名的 onloadonerror 均不触发PASS
www.httpbin.org 的数据外泄 fetch200 — fetch 仍然完成(CSD 不拦截 fetch)INFO
向 jsonplaceholder.typicode.com 的数据外泄 fetch201 — fetch 仍然完成(CSD 不拦截 fetch)INFO
控制台输出[CSD Demo] Simulation completePASS

这是演示的核心成果——并排证据证明,在同一页面上使用相同脚本发起的相同攻击,现在产生了完全不同的结果。

信号缓解前(步骤 2)缓解后(步骤 5)
CDN 脚本加载200 — 所有 4 个 CDN 脚本正常加载已阻断 — 脚本不出现在网络标签中(CSD 已将 src 清除为空字符串)
CDN onload 回调出现 [Supply Chain] Loaded from 消息无回调触发(未发出网络请求)
www.httpbin.org 的数据外泄200 — 数据已外泄200 — fetch 仍然完成(CSD 不拦截 fetch)
向 jsonplaceholder.typicode.com 的数据外泄201 — 数据已外泄201 — fetch 仍然完成(CSD 不拦截 fetch)
CSD 已缓解域名 API0 条已缓解6 条已缓解

每隔 60 秒查询一次 /detected_domains,最多查询 10 次(10 分钟)。查询返回后或 10 分钟上限到达后,继续进行对比表——这些检查仅供参考,不阻断阶段 4 的进行。

缓解后检查已检测域名:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{total_domains: .domain_summary.totalDomains, domains: [.domains_list[]? | {domain: .domain, category: .category}]}'

检查已缓解状态的脚本:

Terminal window
NOW=$(date +%s)
START=$(( NOW - 86400 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{\"startTime\": \"$START\", \"endTime\": \"$NOW\"}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts" \
| jq '{total: (.scripts | length), scripts: [.scripts[]? | {script_name: .script_name, risk_level: .risk_level}]}'
检查项预期状态
基线干净(步骤 1)开始时 0 条已缓解域名PASS / FAIL
之前——攻击成功(步骤 2)脚本加载,数据外泄返回 200/201PASS / FAIL
缓解措施已应用(步骤 3)所有 6 个域名通过 POST 接受(200 或 409)PASS / FAIL
缓解数量已确认(步骤 4)列表中有 6 条PASS / FAIL
之后——脚本加载已阻断(步骤 5)CDN 脚本不出现在网络标签中,fetch 调用仍然完成PASS / FAIL
前后对比(步骤 6)步骤 2 和步骤 5 的证据之间有明显差异PASS / FAIL

阶段 3 完成。 准备好删除所有部署对象后,请前往阶段 4 — 清理