跳到主要内容

工程实践:Mock 热加载从 Web Fuzzer 到模板调试全链路

· 阅读需 7 分钟
Yak ProjectYak Project

在上一篇文章中,我们介绍了 mockHTTPRequest 热加载函数在 MITM 代理场景下的应用——通过完全控制响应来实现“无污染”的客户端测试。今天,我们将这一能力进一步延伸到两个关键场景:

WebFuzzer 中的 Mock 响应:用于漏洞场景模拟、复现与演示

模板代码调试中的模拟响应:便于本地调试匹配器和提取器

这两个新特性共同解决了一个核心痛点:在没有真实漏洞环境的情况下,如何高效地编写、调试和演示安全检测规则?

WebFuzzer 中的 Mock 响应:漏洞场景模拟与复现

使用场景

在日常工作中,我们经常遇到以下困境:

  • 漏洞难以复现:某些漏洞依赖特定的环境配置、时间窗口或竞态条件,不易稳定复现;
  • 演示环境受限:在客户演示或培训场景中,无法直接展示对真实系统的攻击;
  • 匹配器调试困难:编写响应包匹配规则时,需要反复触发真实请求,效率低下,对目标系统造成影响。

工作原理

当你在 WebFuzzer 的热加载代码中定义 mockHTTPRequest 函数后,每次 Fuzzer 发送请求时都会先经过这个 hook:

在底层实现中,当 mockHTTPRequest 被调用并产生模拟响应时,系统会完全跳过真实的 HTTP 请求。

典型应用:漏洞演示与教学

假设我们需要演示一个 SQL 注入漏洞的检测过程,但手头没有可用的漏洞环境。我们可以在 webfuzzer 热加载中添加 mockHTTPRequest 代码:

mockHTTPRequest = func(isHttps, url, req, mockResponse) {
// 模拟一个存在 SQL 注入的登录接口
if str.Contains(url, "/api/login") {
// 检查是否包含注入 payload
if str.Contains(string(req), "' OR '1'='1") {
// 模拟注入成功的响应
successResponse = `HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: *
{"success":true,"message":"登录成功","user":{"id":1,"role":"admin","username":"admin"}}`
mockResponse(successResponse)
return
}

// 正常登录失败
failResponse = `HTTP/1.1 401 Unauthorized
Content-Type: application/json
{"success":false,"message":"用户名或密码错误"}`
mockResponse(failResponse)
}
}

现在,在 WebFuzzer 中发送带有 SQL 注入 payload 的请求,UI 会显示"成功"的响应——就像真的存在漏洞一样。

可以用于以下场景:

  • 安全培训和教学
  • 客户演示(展示检测能力而非实际攻击)
  • 编写和调试匹配器规则

都极为有用。

进阶应用:构建虚拟漏洞靶场

你甚至可以用 Mock 构建一个完整的"虚拟靶场":

mockHTTPRequest = func(isHttps, url, req, mockResponse) {
reqStr = string(req)

// 漏洞1:真实环境命令执行
if str.Contains(url, "/api/exec") {
body = poc.GetHTTPPacketBody(req)
cmd = json.loads(body)['cmd']
println(cmd)
res = exec.System(cmd)~
response = `HTTP/1.1 200 OK
Content-Type: text/plain
` + string(res)
mockResponse(response)
return
}

// 漏洞2:信息泄露
if str.Contains(url, "/.git/config") {
response = `HTTP/1.1 200 OK
Content-Type: text/plain
[core]
repositoryformatversion = 0
filemode = true
[remote "origin"]
url = git@github.com:company/internal-project.git`
mockResponse(response)
return
}

// 漏洞3:SSRF
if str.Contains(url, "/api/fetch") && str.Contains(reqStr, "127.0.0.1") {
response = `HTTP/1.1 200 OK
Content-Type: application/json
{"status":"success","content":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:..."}`
mockResponse(response)
return
}

// 默认:返回正常页面
}

模板代码调试:支持模拟响应的本地调试

问题背景

在编写 Yaml 风格的检测模板时,我们经常需要:

1、先构思匹配规则(matchers)和数据提取器(extractors)

2、然后反复发送请求来验证规则是否正确

3、如果不正确,修改规则后再次发送请求……

这个循环存在几个问题:

  • 依赖真实目标:需要有可用的测试环境,想调代码需要先启动靶场
  • 效率低下:每次验证都要发真实请求,可能由于网络问题造成每次测试都花费很多时间
  • 结果不可控:服务端响应可能变化

解决方案:模拟响应

现在,WebFuzzer 支持将匹配器和提取器导出为模板代码,并且在模板调试过程中支持传入模拟响应。这个模拟响应会在模板执行时完全替代真实的 HTTP 请求。

核心流程:

使用方式

步骤一:在 WebFuzzer 中配置匹配器

假设我们要检测一个返回用户信息的 API 是否存在敏感信息泄露:

匹配器配置:

步骤二:导出为 YAML 模板

点击"导出模板"后,会生成类似以下的 YAML:

id: WebFuzzer-Template-FjBpUiDb
info:
name: WebFuzzer Template FjBpUiDb
severity: low
description: write your description here
reference:
- https://github.com/
- https://cve.mitre.org/
metadata:
max-request: 1
shodan-query: ""
verified: true
yakit-info:
sign: a47e000c5fc61a12b66f0af17c22b9cc
http:
- raw:
- |-
@timeout: 30s
POST /api/exec HTTP/1.1
Content-Type: application/json
Host: {{Hostname}}
{"cmd": "echo -n \"root\" | md5"}
max-redirects: 3
disable-cookie: true
matchers:
- type: word
part: body
words:
- 63a9f0ea7bb98050796b649e85481845
condition: and

步骤三:使用模拟响应调试

在模板调试界面,传入模拟响应:

执行后,可以看到匹配成功,生成漏洞报告,匹配的响应是我们刚才设置的模拟响应。

底层实现

在模板执行层,Mock 响应通过 nuclei.mockHTTPRequest 选项注入,在编写YAK 代码调用 yaml 模板时同样可以实现模拟响应。

// nuclei_executor.yak
nucleiPoC = MITM_PARAMS["CURRENT_NUCLEI_PLUGIN"]
mock_response = MITM_PARAMS["NUCLEI_MOCK_RESPONSE"]
execNuclei = func(target) {
opts = [
nuclei.exactTemplateIns(nucleiPoC),
nuclei.timeout(10),
]

// 如果有 mock 响应,注入 mockHTTPRequest 选项
if mock_response != nil {
opts.Append(nuclei.mockHTTPRequest((https, url, req, mockResponse) => {
mockResponse(mock_response)
}))
}

res, err = nuclei.Scan(target, opts...)
// ...
}

这确保了整个模板执行过程中,所有 HTTP 请求都会被模拟响应替代——不会发出任何真实的网络请求

实战案例:CVE 漏洞检测模板的开发流程

让我们通过一个完整的案例,来测试模拟响应的用法。

场景:开发 CVE-2024-XXXX 的检测模板

假设这是一个需要特定响应头才能触发的漏洞,但我们手头没有漏洞环境。

Phase 1:构造模拟响应

HTTP/1.1 200 OK
Server: VulnerableApp/1.2.3
X-Debug-Mode: enabled
X-Internal-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Content-Type: application/json
{"status":"ok","debug":true,"internal_paths":["/admin","/config","/backup"]}

Phase 2:编写检测规则

Phase 3:生成模板并模拟响应调试

生成模板:

id: WebFuzzer-Template-FXTvoTiO
info:
name: WebFuzzer Template FXTvoTiO
severity: low
description: write your description here
reference:
- https://github.com/
- https://cve.mitre.org/
metadata:
max-request: 1
shodan-query: ""
verified: true
yakit-info:
sign: 857b6edd340cf92b023bc0d47ca16403
http:
- raw:
- |+
@timeout: 30s
POST /debug HTTP/1.1
Content-Type: application/json
Host: {{Hostname}}
max-redirects: 3
disable-cookie: true
matchers-condition: and
matchers:
- type: word
part: header
words:
- 'X-Debug-Mode: enabled'
condition: and
- type: regex
part: header
regex:
- X-Internal-Token:\s*ey[A-Za-z0-9_-]+
condition: and
- type: word
part: body
words:
- internal_paths
condition: and
# Generated From WebFuzzer on 2025-12-26 11:43:09

设置模拟响应并执行,成功匹配关键信息,生成漏洞报告。

总结

Mock 响应功能的引入,标志着安全检测规则开发进入了一个新阶段。我们不再受制于真实环境的可用性,而是可以在完全可控的条件下进行高效的规则开发、测试和演示。


本文首发于 Yak Project 公众号,阅读原文