mcpField
W
webfuzzer-hotpatch

webfuzzer-hotpatch

github.com/yaklangSecurity10123 installsUpdated 15w ago
Repository

About webfuzzer-hotpatch

webfuzzer-hotpatch is a YAK hot-patch skill for hooks in a single Yakit Web Fuzzer tab's request flow. It covers request and response rewriting, retries, failure checks, parameter extraction, and mock responses, with guidance on concurrency and self-testing.

Key features

  1. 01Documents six Web Fuzzer hooks
  2. 02Rewrites requests and decrypts responses
  3. 03Controls retries and custom failure checks
  4. 04Extracts parameters and supports fuzztag
  5. 05Includes crypto recipes and self-test methods
  6. 06Explains concurrent state handling

Use cases

  1. 01Encrypt and sign plaintext requests in the Fuzzer
  2. 02Decrypt responses to inspect their plaintext
  3. 03Choose retries or failure status from business responses
  4. 04Use extracted parameters in multi-step tests

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/yaklang/yak-skills --skill webfuzzer-hotpatch

After installing, type/webfuzzer-hotpatchin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

examples/
after-request.yak
before-request.yak
combo-aescbc-plaintext-roundtrip.yak
combo-rsa-aesgcm-hybrid.yak
combo-sign-and-encrypt.yak
custom-failure-checker.yak
fuzztag-handle.yak
mirror-http-flow.yak
mock-http-request.yak
retry-handler.yak

Details

From the project README

SKILL: Yakit Web Fuzzer 热加载 (Hot Patch)

AI LOAD INSTRUCTION: 这是三层热加载体系中的"模块级 Web Fuzzer"专题。Web Fuzzer 热加载作用于单个 Fuzzer Tab 的发包流程,最典型的用途是"内网加密对抗"(请求加密、响应解密、签名注入)与"自动化决策"(重试、业务失败判定)。先读 Hook 签名与返回值语义,再看 examples/ 下按 Hook 命名的示例,每个都可 yak <file> 自测。处理"前端加密各种 HACK / 让用户看到明文"时直接看第 5 节的组合配方(examples/combo-*.yak);写任何热加载前务必读第 6 节"并发与全局变量"避免竞争崩溃。

0. 相关路由

  • 总入口与三层体系:yak
  • MITM 热加载(代理侧劫持/镜像/入库):mitm-hotpatch
  • 全局热加载(先于模块执行、MITM/Fuzzer 共享):global-hotpatch

1. Hook 签名与返回值语义

Web Fuzzer 热加载的 hook 与 MITM 有关键区别:劫持类通过 返回值 提交修改(不是 forward/drop)。

Hook签名作用提交方式
beforeRequest(https, originReq, req) -> req请求出站前改写(加密/签名/加头)return 新请求
afterRequest(https, originReq, req, originRsp, rsp) -> rsp响应回显前改写(解密/格式化)return 新响应
retryHandler(https, retryCount, req, rsp, retry)重试触发时决定下一步retry([newReq])
customFailureChecker(https, req, rsp, fail)自定义"失败"判定fail("原因")
mirrorHTTPFlow(req, rsp, params) -> params提取参数供 {{params(name)}}return map
mockHTTPRequest(https, url, req, mockResponse)离线/无服务时用本地响应mockResponse(rspStr)

注意:Web Fuzzer 的 mirrorHTTPFlow(req, rsp, params) 与 MITM 的 mirrorHTTPFlow(isHttps, url, req, rsp, body) 签名不同,不要混用。

2. 核心场景一:内网加密对抗

现代 Web 应用常对请求/响应做加密或签名。把加解密/签名逻辑沉淀到热加载,就能在 Fuzzer 里直接对 明文 做 fuzz,发包时自动加密、回显时自动解密。

flowchart LR
    Plain["Fuzzer 里写明文请求"] -->|beforeRequest 加密/签名| Wire["真正出站的密文/带签名请求"]
    Wire --> Server["目标服务器"]
    Server -->|密文响应| After["afterRequest 解密"]
    After --> View["Fuzzer 里看到明文响应"]
场景Hook示例
timestamp+nonce+HMAC 签名注入beforeRequestexamples/before-request.yak
AES-CBC 响应解密(Fuzzer 看明文)afterRequestexamples/after-request.yak

国密(SM4-CBC / SM2 / SM3)同理,把 codec.AESCBC* 换成 codec.SM4* / codec.Sm3 即可。

3. 核心场景二:自动化决策(重试 / 失败判定)

文章 043 引入的两个函数把"人工分析响应再决定怎么办"自动化、代码化:

场景Hook示例
405→POST / 429 退避 / 401 放弃 / 5xx 重试retryHandlerexamples/retry-handler.yak
200 OK 但 body 含失败关键词判为失败customFailureCheckerexamples/custom-failure-checker.yak
目标未上线时用本地响应联调mockHTTPRequestexamples/mock-http-request.yak
  • retryHandler 需配合 yakit Fuzzer 的重试配置(开启重试 + 指定失败状态码)使用。
  • customFailureChecker 解决"协议层 200、业务层失败"的爆破筛选难题。
  • mockHTTPRequest 让 payload 渲染/重试/失败判定在没有真实服务时也能跑通联调。

4. 核心场景三:fuzztag 与关联测试

场景机制示例
动态计算哈希 payload`{{yak(hashmd5,admin)}}`
多步请求提取 token/csrfmirrorHTTPFlow 返回 map → {{params(name)}}examples/mirror-http-flow.yak

热加载里定义的普通函数 f = func(param){ return [...] } 即可作为 {{yak(f|参数)}} 标签被调用,返回数组的每个元素是一个 payload。

5. 前端加密对抗组合配方(让用户看到明文)

单个 hook 解决单点问题,真实"前端加密 HACK"往往要 多个 hook 组合:发包侧加密/签名,回包侧解密,让你在 Fuzzer 里始终面对 明文。这正是绕过前端加密做爆破/测试的核心套路。

flowchart LR
    P["你写的明文 payload"] -->|beforeRequest / fuzztag 加密+签名| W["出站密文(过验签)"]
    W --> S["目标服务器"]
    S -->|密文响应| D["afterRequest / mirrorHTTPFlow 解密"]
    D --> V["Fuzzer 里看到明文, 一眼判断成功"]
组合配方涉及 hook对抗的前端防护示例
AES-CBC 写明文/看明文往返beforeRequest + afterRequestCryptoJS AES-CBC 静态密钥examples/combo-aescbc-plaintext-roundtrip.yak
加密 + HMAC 验签 双重防护beforeRequest + afterRequestAES 加密叠加签名防篡改examples/combo-sign-and-encrypt.yak
RSA-OAEP + AES-GCM 混合加密{{yak(...)}} fuzztag + mirrorHTTPFlow动态公钥 + 非对称包裹对称密钥examples/combo-rsa-aesgcm-hybrid.yak

要点:

  • 请求侧用 beforeRequest(整包加密/签名)或 {{yak(fn|...)}} fuzztag(只加密某个字段)。
  • 响应侧用 afterRequest(直接把响应改成明文回显)或 mirrorHTTPFlow(把解密结果提取成变量,配合序列 {{params(name)}},并在结果表里一眼看出成功)。
  • 动态密钥/公钥用 Web Fuzzer 序列:Step0 取密钥 → 数据提取器存 publicKey/privateKey → Step1 {{params(publicKey)}} 引用(见混合加密示例头注释)。
  • 常用算法 API:codec.AESCBCEncryptWithPKCS7Padding / codec.AESGCMEncryptWithNonceSize12 / codec.RSAEncryptWithOAEP / codec.HmacSha256,国密换成 codec.Sm4* / codec.SM2*。

关于"明文密码传输"为什么值得测:参见文章 183——前端加密只是抬高门槛,密码本质仍在通信中可还原;把链路解密成明文后,常规注入/爆破/逻辑测试就全部恢复可用。

6. 并发与全局变量:尽量用"只读常量",否则会崩

这是热加载最容易踩的崩溃坑。 MITM / Web Fuzzer 会 并发 地对多个请求调用同一个 hook(同一份脚本实例)。如果你的 hook 去 读写同一个顶层可变全局变量(例如 append 到全局 slice、给全局 map 赋值、累加全局计数器),多个 goroutine 同时写就会触发 data race,轻则结果错乱,重则直接 panic 崩溃。

规则:

  • 配置/密钥/IV/规则表等放顶层,但当作"只读常量":加载时赋值一次,hook 内 绝不修改。这种用法天然并发安全(本节所有加密组合示例都是这么写的)。
  • 不要在 hook 里写共享可变全局。需要累加/收集时:
    • 优先把状态留在 函数局部 或通过返回值传出(mirrorHTTPFlow 返回 map、afterRequest 返回包)。
    • 确实要跨请求聚合,用并发安全容器/锁:sync.Map、sync.NewMutex() 加锁,或 yakit 的 db.* / risk.* 落库,而不是裸 append 全局 slice。
// 反例(并发会崩): 多个请求同时 append 同一个全局 slice
RESULTS = []
mirrorHTTPFlow = func(req, rsp, params) { RESULTS = append(RESULTS, req); return {} }  // 危险!

// 正例: 顶层只放只读常量, 结果通过返回值带出
AES_KEY = codec.DecodeHex("3132...")~   // 只读常量, 不再修改
afterRequest = func(https, oreq, req, orsp, rsp) {
    return poc.ReplaceHTTPPacketBody(rsp, decrypt(AES_KEY, poc.GetHTTPPacketBody(rsp)))
}

本库 mirror-* 单 hook 示例为了"自测可断言"用了全局 slice/map 累加——那是 单线程命令行自测 的演示写法;放进真实并发的 MITM/Fuzzer 时,请按上面的规则改成只读常量 + 返回值/加锁。

7. 标准写法:hook 函数 + YAK_MAIN 自测

beforeRequest = func(https, originReq, req) {
    // 改写 req
    return req
}

func runSelfTest() {
    // 构造 mock 请求, 调用 hook, assert 返回值
}

if YAK_MAIN {
    runSelfTest()
}

YAK_MAIN 区分运行环境:

  • yak xxx.yak 命令行:YAK_MAIN = true,跑自测。
  • yakit Fuzzer 热加载窗口:YAK_MAIN = false,仅注册 hook。
各 Hook 的自测 mock 方式
Hook自测验证方式
beforeRequest / afterRequest构造 mock 请求/响应,断言返回包内容(可对加密结果做反向解密验证 roundtrip)
retryHandler自定义 retry callback(func(args...)),断言调用次数与新请求内容
customFailureChecker自定义 fail callback,断言是否被标记失败
mirrorHTTPFlow直接调用,断言返回 map 的提取字段
mockHTTPRequest自定义 mockResponse callback,验证目标触发

8. 常用 codec / poc API 速查

用途API
AES-CBC 加/解密codec.AESCBCEncrypt(key, data, iv)~ / codec.AESCBCDecrypt(key, cipher, iv)~
Base64 编/解码codec.EncodeBase64(b) / codec.DecodeBase64(s)~
HMAC-SHA256(返回字节)codec.EncodeToHex(codec.HmacSha256(key, data))
哈希codec.Md5(s) / codec.Sha256(s) / codec.EncodeToHex(codec.Sm3(s))
状态码poc.GetStatusCodeFromResponse(rsp)
改方法poc.ReplaceHTTPPacketMethod(req, "POST")
改 body / headerpoc.ReplaceHTTPPacketBody / poc.ReplaceHTTPPacketHeader
取请求 method/pathpoc.GetHTTPRequestMethod(req) / poc.GetHTTPRequestPath(req)

9. 验证

cd /Users/v1ll4n/Projects/yaklang
go run common/yak/cmd/yak.go skills/webfuzzer-hotpatch/examples/before-request.yak

# 与 Yakit gRPC 同款执行路径 (MutateHookCaller); 验证 {{yak(...)}} fuzztag:
go build -o /tmp/yak ./common/yak/cmd/yak.go
printf 'GET / HTTP/1.1\r\nHost: t.example.com\r\n\r\n' > /tmp/req.txt
/tmp/yak hotpatch-webfuzzer --script skills/webfuzzer-hotpatch/examples/fuzztag-handle.yak \
    --request /tmp/req.txt --fuzztag '{{yak(hash|md5,hello)}}'

每个示例应:10 秒内完成、assert 全过、log 全英文、出现 ... self test passed。

参考来源

  • yak-project-public 043 (2025-07-25) Web Fuzzer 新的热加载函数——重试控制与错误处理
  • yak-project-public 183 (2023-09-14) 渗透测试高级技巧 分析验签与前端加密(一)(HMAC 验签 + AES-CBC,组合配方来源)
  • yak-project-public 177 (2023-10-11) 渗透测试高级技巧(二) 对抗前端动态密钥与非对称加密防护(RSA-OAEP + AES-GCM 混合,混合加密组合来源)
  • yak-project-public 084 (2024-12-05) 渗透测试高级技巧(三) 被前端加密后的漏洞测试
  • yak-project-public 270 (2022-07-28) 前端 AES-ECB 加密 Web 安全测试实战
  • yak-project-public 282/285 (2022-05) Yakit Web Fuzzer 终极能力强化 热加载 Fuzz
  • yak-project-public 167 (2023-11-17) Web Fuzzer 进阶
  • 引擎实现:common/yak/script_engine_for_fuzz.go

Comments

Markdown supported