跳到主要内容

3.3 MITM进阶:热加载技术

我们在前面的小节基本介绍了 Yakit MITM 的基础功能和插件系统,本节将深入探讨 MITM 的核心技术之一——热加载技术,它使得安全测试人员能够在不中断代理服务的情况下动态调整和扩展 MITM 功能。

注意:这一章对用户的要求会增加,需要用户有基本的Yaklang编程能力和计算机理解能力。

3.3.1 基本概念

热加载:一种允许用户在不中断服务运行的情况下,动态加载、更新和卸载各种功能模块的技术机制。

概念解释

热加载技术是Yakit MITM模块的核心创新,它允许安全测试人员在不中断代理服务的情况下,动态加载、更新和卸载各种安全功能模块。与传统的静态代理不同,热加载机制使Yakit能够实时响应测试需求变化,大幅提升测试效率和灵活性。

热加载的工作原理基于事件驱动模型,系统在HTTP请求和响应的各个关键处理阶段设置了多个"钩子"(Hook点),当流量经过这些Hook点时,系统会触发相应的事件,并执行已加载的处理函数。这种设计使得安全测试人员可以针对HTTP通信的不同阶段实现精确的拦截和处理逻辑,从而实现从简单的流量监控到复杂的自动化漏洞利用等多种功能,且所有模块均可在运行时动态调整,无需重启代理服务。

用户可以跟随下图指引通过左侧边栏进入热加载操作的UI界面:

图:Yakit MITM 劫持 HTTP Request 代码模板界面

这个界面实现了3.3.1节中提到的基本概念,用户可以在此编写Yaklang代码来实现流量的镜像获取、劫持修改等功能。通过注释中提示的参数(isHttps、url、req、rsp、body等),用户可以访问HTTP通信的各个组成部分,实现精确的流量分析和处理。界面设计为左侧为代码编辑区,右侧为功能控制区,支持代码模板和保存功能,方便用户快速开发和复用热加载脚本。用户在编辑完代码需要生效时,点击“热加载”按钮即可让代码加载进内存,无需重启服务器。

钩子函数:关键Hook点

钩子函数(也称为关键 Hook 点)是指在 Yakit MITM 热加载技术中,系统预先设定在 HTTP 通信流程中的特定事件触发位置,用户可以在这些位置注册自定义代码块。当系统检测到相应的事件发生时,会自动调用这些用户定义的函数,并将相关的流量数据和上下文参数传递给这些函数执行。这些钩子函数有以下特点:

  1. 事件驱动:基于 HTTP 通信流程中的关键事件触发

  2. 参数传递:自动接收相关流量数据和上下文参数(如 isHttps、url、req、rsp、body 等)

  3. 执行时机:在特定的 HTTP 处理阶段被系统自动调用

  4. 处理灵活:可以实现监控、拦截、修改等多种操作

  5. 无需重启:可以在代理服务运行过程中动态加载和更新

Yakit MITM 提供了丰富的钩子函数,涵盖了 HTTP 通信流程的各个关键阶段。以下是完整的钩子函数列表及其功能总览(用户只需要使用自己感兴趣的钩子函数即可,实际使用中,并不需要定义所有钩子函数):

读者看到这里,可能感觉函数非常多,理解起来有些复杂,我们使用一张图来表示整个过程:

图:Yakit MITM请求响应处理与流量镜像Hook流程

HTTP请求响应处理阶段是整个流程的核心,采用同步串行执行方式。当客户端发起请求时,首先触发hijackHTTPRequest进行请求包劫持,这是主要的请求拦截点,使用频率最高;接着执行beforeRequest进行请求的最终处理,提供请求发送前的最后修改机会;然后将请求发送到服务器并接收响应;服务器响应返回后,触发hijackHTTPResponse进行响应包劫持,这是主要的响应拦截点;最后执行afterRequest进行响应的最终处理,提供响应返回前的最后修改机会,然后将响应返回给客户端。

流量镜像阶段和存储处理阶段在HTTP请求响应处理完成后异步执行,不影响正常的HTTP响应速度。流量镜像阶段按顺序执行mirrorHTTPFlow全流量镜像、mirrorFilteredHTTPFlow过滤后流量镜像,以及mirrorNewWebsite等特定条件镜像,其中mirrorFilteredHTTPFlow使用频率最高且推荐使用,而mirrorHTTPFlow因包含所有流量(包括被过滤的)性能开销较大不推荐使用。存储处理阶段通过hijackSaveHTTPFlow进行流量入库前的最后处理,可以修改流量记录、添加标签、过滤敏感信息等,然后将流量存储到数据库。在实际应用中,hijackHTTPRequest适用于请求修改、参数注入、认证处理等场景,hijackHTTPResponse适用于响应修改、数据过滤、安全检查,mirrorFilteredHTTPFlow用于流量监控和日志记录,hijackSaveHTTPFlow用于数据清洗和标签添加。需要注意的是,应避免使用mirrorHTTPFlow以优化性能,理解同步和异步执行的区别,按需使用钩子函数而非全部定义,并妥善处理钩子函数中的异常以免影响整个HTTP流程。这种设计让用户可以在HTTP通信的各个关键节点插入自定义逻辑,实现灵活的流量处理和分析功能。

3.3.2 详解钩子函数

根据前文的介绍,按照流量处理的阶段,我们基本可以把钩子函数分成三类,分别为:

  1. 镜像流量类:这类钩子函数都以mirror...开头,这类函数一般不涉及流量的修改,在这里编写代码一般只能观察和分析流量,无法对通信产生直接影响。

  2. HTTP请求响应劫持类:同步串行执行的可以动态修改请求数据包与响应,直接影响通信过程;

  3. 存储处理类:这个阶段的函数只有一个: hijackSaveHTTPFlow,这个钩子函数目的主要是允许用户自定义在流量存储到History中的过程,例如:

    1. 用户希望包含某一个关键字的流量染成红色,可以在hijackSaveHTTPFlow定义染色操作;

    2. 前后端通信是加密的,但是用户可以在hijackSaveHTTPFlow中解密通信,把明文数据保存在数据库中,方便分析;

接下来我们会分别对上面三种钩子函数进行详细解读。

镜像流量类

镜像流量类钩子函数以mirror开头,主要用于流量监控和分析,它们在HTTP请求响应处理完成后异步执行,不影响正常的HTTP通信性能。

  • mirrorHTTPFlow - 全流量镜像

    • 触发时机:每个HTTP请求响应完成后都会触发,无论流量是否被过滤规则拦截。

    • 使用建议:除非用户知道自己在做什么,否则不推荐频繁使用,因为包含大量无关流量(如广告、统计、CDN资源等),会造成性能开销和数据冗余。

  • mirrorFilteredHTTPFlow - 过滤后流量镜像

    • 触发时机:只有通过Yakit过滤规则的HTTP流量才会触发。(用户可以在下图位置点击配置过滤器)

图:Yakit镜像流量过滤器界面

- **使用说明:**通过配置过滤器排除`.css`、`.js`、`.png`等静态资源以及广告域名后,该函数只会捕获真正有价值的业务请求,如`https://example.com/api/login`、`https://example.com/api/checkout`、`https://example.com/admin/dashboard`等核心业务接口。这样你就能专注于分析关键业务逻辑的安全问题,而不被大量静态资源、CDN请求、第三方统计脚本等噪音数据干扰,从而大大提高渗透测试和安全分析的效率,让安全研究人员能够快速定位到真正存在安全风险的API端点和管理后台入口。
  • mirrorNewWebsite - 新网站发现镜像

    • **触发时机:**当发现一个全新的网站域名时触发,每个域名在整个会话中只会触发一次。

    • **使用说明:**该函数专门用于网站资产发现和初始侦察阶段。当你对目标进行扫描时,无论是访问https://example.comhttps://api.example.com还是https://admin.example.com,每个不同的域名只会在首次发现时触发一次。这对于构建目标资产清单、进行子域名枚举验证、或者在大规模扫描中快速识别新发现的服务入口点非常有用。

    • **详细解读:**当访问以下URL序列时

https://192.168.1.100:8080/abc/
https://192.168.1.100:8080/abc/12
https://192.168.1.100:8080/abc/13
https://localhost:8080/abc/14?a=2&&c=1

mirrorNewWebsite只会触发两次调用:第1次:首次发现域名192.168.1.100:8080时触发;第2次:首次发现域名localhost:8080时触发;

  • mirrorNewWebsitePath - 新路径发现镜像

    • **触发时机:**当在已知网站上发现新的URL路径时触发,相同路径在同一域名下只会触发一次。

    • **使用说明:**该函数用于路径和目录发现。例如,在example.com域名下,首次访问/admin/login/api/users/upload/files等路径时会分别触发一次。这对于目录爆破验证、API端点发现、以及构建网站结构图谱极其有用,帮助安全研究人员快速了解目标应用的功能模块分布。

    • 详细解读:当访问以下URL序列时:

      https://192.168.1.100:8080/abc/
      https://192.168.1.100:8080/abc/12
      https://192.168.1.100:8080/abc/13
      https://192.168.1.100:8080/abc/14
      https://192.168.1.100:8080/abc/14?a=1
      https://192.168.1.100:8080/abc/14?a=2
      https://192.168.1.100:8080/abc/14?a=2&&c=1
      https://localhost:8080/abc/14?a=2&&c=1

      mirrorNewWebsitePath 会触发 5次 调用:

      1. 第1次:在域名 192.168.1.100:8080 下首次发现路径 /abc/ 时触发。

      2. 第2次:在域名 192.168.1.100:8080 下首次发现路径 /abc/12 时触发。

      3. 第3次:在域名 192.168.1.100:8080 下首次发现路径 /abc/13 时触发。

      4. 第4次:在域名 192.168.1.100:8080 下首次发现路径 /abc/14 时触发。(注意:后续带有参数 ?a=1, ?a=2, ?a=2&&c=1 的请求访问的仍然是 /abc/14 这个路径,因此不会重复触发)。

      5. 第5次:在域名 localhost:8080 下首次发现路径 /abc/14 时触发。(虽然 /abc/14 路径在 192.168.1.100:8080 域名下已出现过,但对于新域名 localhost:8080 来说,这是首次发现该路径,因此会触发)。

  • mirrorNewWebsitePathParams - 新参数组合发现镜像

    • **触发时机:**当发现相同路径下的新参数组合时触发,相同参数结构的请求只会触发一次。

    • **使用说明:**该函数专注于参数级别的去重分析。例如,对于路径/api/user,首次遇到?id=123&type=admin这种参数结构时会触发,但后续的?id=456&type=user(相同参数名但不同值)不会重复触发。这对于API参数发现、SQL注入点识别、以及参数污染测试的准备工作非常重要,能够帮助研究人员快速识别所有可能的攻击面而不被重复的参数值干扰。

    • 详细解读:当访问以下URL序列时:

https://192.168.1.100:8080/abc/
https://192.168.1.100:8080/abc/12
https://192.168.1.100:8080/abc/13
https://192.168.1.100:8080/abc/14
https://192.168.1.100:8080/abc/14?a=1
https://192.168.1.100:8080/abc/14?a=1 # 重复
https://192.168.1.100:8080/abc/14?a=2 # 结构同上
https://192.168.1.100:8080/abc/14?a=2&&c=1
https://192.168.1.100:8080/abc/14?a=2&&c=1 # 重复
https://localhost:8080/abc/14?a=2&&c=1

mirrorNewWebsitePathParams 会触发 7次 调用:

HTTP请求响应劫持类

这类钩子函数是 Yakit MITM 流程修改数据包和通信过程的核心函数,它们同步串行执行,允许用户在请求发送到服务器之前和响应返回给客户端之前,动态地检查、修改甚至阻止 HTTP 流量。因为它们直接介入和改变通信过程,所以对性能和稳定性有直接影响,需要谨慎使用。

  • hijackHTTPRequest** - 劫持 HTTP 请求**

    • 触发时机: 在客户端发起请求后,Yakit 准备将请求发送到目标服务器之前触发。这是最主要的请求拦截和修改点。

    • 功能说明: 允许用户访问和修改即将发送的整个 HTTP 请求,包括请求方法、请求头和请求体。用户可以在此函数中决定是放行原始请求、修改后放行,还是直接构造一个响应返回给客户端(不访问真实服务器),或者丢弃该请求。

    • **使用说明:对请求的任何修改都会直接影响到服务器收到的内容,**用户在使用这个钩子函数的时候,要万分小心。一般情况下,这个函数会被用来注入特定Header,身份认证的伪造或绕过,直接注入一些新的参数等。

我们以一个例子来解释这个函数实际的用法,具体的操作流程主要是:1. 用户修改代码;2. 点击热加载启动按钮,加载到内存;3. 通过流量,观察流量是否被修改。读者可以按照下图所示内容来操作

图:Yakit MITM HTTP请求响应劫持配置界面

在上图的代码示例中,我们可以看到 hijackHTTPRequest 函数的实际应用。代码首先通过 str.Contains(url, '``www.example.com``') 判断请求的目标URL是否包含特定域名,当条件满足时,使用 poc.ReplaceHTTPPacketHeader() 函数向请求中添加一个自定义的HTTP头部 X-HotPatch-Key: Value-By-HotPatch,最后通过 forward(req) 将修改后的请求发送到目标服务器。

从右侧的请求详情面板可以清楚地看到,原始请求经过 hijackHTTPRequest 函数处理后,成功添加了 X-HotPatch-Key: Value-By-HotPatch 这个自定义头部(如红框标注所示),证明热加载代码已经生效。这种方式常用于身份认证绕过、API密钥注入、调试标记添加等渗透测试场景,让安全研究人员能够动态地向目标服务器发送包含特定标识或认证信息的请求。

在上面案例中,核心钩子函数实现为:

// hijackHTTPRequest 会在过滤后的请求到达Yakit MITM前被调用,可以通过该函数提前将请求修改或丢弃
// isHttps 请求是否为https请求
// url 网站URL
// req 请求
// forward(req) 提交修改后的请求,如果未被调用,则使用原始的请求
// drop() 丢弃请求
hijackHTTPRequest = func(isHttps, url, req, forward /*func(modifiedRequest []byte)*/, drop /*func()*/) {
if str.Contains(url, `www.example.com`) {
req = poc.ReplaceHTTPPacketHeader(req, "X-HotPatch-Key", "Value-By-HotPatch")
forward(req)
}
}
  • hijackHTTPResponse / hijackHTTPResponseEx - 劫持 HTTP 响应

    • 触发时机: 在 Yakit 从目标服务器接收到响应后,准备将响应发送回客户端之前触发。这是最主要的响应拦截和修改点。

    • 功能说明: 允许用户访问和修改从服务器收到的整个 HTTP 响应,包括状态码、响应头和响应体。用户可以决定是放行原始响应、修改后放行,还是直接丢弃响应或替换为自定义响应。两个函数的主要区别在于 hijackHTTPResponseEx 能够同时获取到对应的请求数据,便于基于请求内容来决定如何处理响应。

    • 使用说明: 对响应的任何修改都会直接影响到客户端收到的内容,常用于响应内容替换、安全策略绕过、数据解密美化等场景。通常情况下,只需要实现 hijackHTTPResponsehijackHTTPResponseEx 其中一个函数即可,如果需要根据请求内容来处理响应,建议使用 hijackHTTPResponseEx

接下来我们使用一个简单的例子来介绍hijackHTTPResponse,我们准备下面这段代码配合图中操作来实现:

// hijackHTTPResponseEx 是hijackHTTPResponse的扩展,能够获取到响应对应的请求,会在过滤后的响应到达Yakit MITM前被调用,可以通过该函数提前将响应修改或丢弃
// !!! 通常实现hijackHTTPResponse 或 hijackHTTPResponseEx 其中一个函数即可
// isHttps 请求是否为https请求
// url 网站URL
// rsp 响应
// forward(req) 提交修改后的响应,如果未被调用,则使用原始的响应
// drop() 丢弃响应
hijackHTTPResponse = func(isHttps /*bool*/, url /*string*/, rsp /*[]byte*/, forward /*func(modifiedResponse []byte)*/, drop /*func()*/) {
// Example:
if str.Contains(string(rsp), "Example Domain") {
rsp = str.ReplaceAll(
rsp,
`Example Domain`,
"Yakit Hot Patch Modified Name",
)
forward(rsp)
}
}

图:Yakit MITM HTTP请求响应劫持界面展示

从图中可以看到这个功能的实际效果:当用户访问 www.example.com 时,原本应该显示 "Example Domain" 的页面标题被成功替换为 "Yakit Hot Patch Modified Name",浏览器中显示的内容完全按照代码中的修改逻辑进行了改变,证明了响应劫持功能的有效性,这种技术在渗透测试中常用于绕过前端限制、修改错误提示或进行内容替换测试。

一般来说,hijackHTTPResponseExhijackHTTPResponse只有传入参数的差别,具体定义对比如下:

两个函数的本质区别在于信息获取的完整性。hijackHTTPResponse 是轻量级的响应拦截器,仅能基于响应内容、URL和协议类型进行判断和修改;而 hijackHTTPResponseEx 是增强版本,通过额外提供请求信息,使得用户可以基于请求-响应的完整上下文进行更精确的判断和处理。两者都在同一时机被调用,具有相同的修改和丢弃能力,区别仅在于可用信息的丰富程度,用户根据实际需求的复杂度选择合适的函数实现即可。

注意:为了避免冲突,用户如果要使用,只推荐用户在这两个函数中进行二选一实现。

  • beforeRequest - 请求最终修改钩子

    • 触发时机: 在请求即将发送到目标服务器的最后时刻被调用,位于 hijackHTTPRequest 处理完成之后。这是对请求进行最终修改的机会,确保所有修改都能在请求真正发送前生效。

    • 功能说明: 允许用户对经过 hijackHTTPRequest 处理后的请求进行最后一次检查和修改。该函数同时提供原始请求(oreq)和经过hijack修改后的请求(req),用户可以基于这两个版本的对比来决定是否需要进一步修改。与hijackHTTPRequest不同的是,beforeRequest通过返回值来提交修改后的请求,如果没有返回值则使用hijack阶段修改后的请求。

    • 使用说明: 这个钩子函数与其他函数略有区别,它可以直接获取到hijackHTTPRequest处理后的结果,允许用户统一对所有请求做最终调整。重要特性:这一步的修改是对用户不可见的 - 如果用户触发手动劫持,在劫持界面看到的内容是beforeRequest处理之前的状态,而beforeRequest的修改会在用户确认发送后才被应用。这意味着beforeRequest中的修改不会影响用户劫持时的可视化界面,常用于添加全局性的请求头、统一的身份认证信息、或者不希望用户感知到的底层调整,确保请求的完整性和正确性。

图:HTTP请求劫持流程与前后端修改阶段示意

为了更好地理解Yakit中HTTP请求劫持的完整处理流程,我们通过一个实际的代码示例来演示`hijackHTTPRequest`和`beforeRequest`两个关键函数的协作机制。在这个例子中,我们分别在两个处理阶段添加不同的HTTP头部标记,通过观察最终请求中的头部信息,可以清晰地验证每个劫持函数的执行顺序和叠加效果。这种分层处理的设计让我们既能进行自动化的请求预处理,又能在用户确认后进行最终的精细调整。

图:Yakit MITM手动劫持请求流程示意图

图:Yakit MITM 自动放行劫持请求修改结果

通过上述截图可以看到,原始的HTTP请求经过两个劫持阶段后,成功添加了两个标记头部:`X-Hijacked-Modified`和`X-Before-Request`。这完美验证了我们的处理流程:首先`hijackHTTPRequest`在MITM拦截阶段自动执行并添加第一个标记,然后用户在界面上看到修改后的请求并选择放行,最后`beforeRequest`在请求发送前添加第二个标记。这种设计的优势在于既保证了自动化处理的效率,又给用户提供了完全的控制权,同时通过函数的分层调用确保了修改的可追溯性和调试的便利性。

用户可以参考如下代码来手动试试:

```Go
// hijackHTTPRequest 会在过滤后的请求到达Yakit MITM前被调用,可以通过该函数提前将请求修改或丢弃
// isHttps 请求是否为https请求
// url 网站URL
// req 请求
// forward(req) 提交修改后的请求,如果未被调用,则使用原始的请求
// drop() 丢弃请求
hijackHTTPRequest = func(isHttps, url, req, forward /*func(modifiedRequest []byte)*/, drop /*func()*/) {
if str.Contains(url, `example.com`) {
req = poc.ReplaceHTTPPacketHeader(
req,
"X-Hijacked-Modified",
"Modified by hijackHTTPRequest",
)
forward(req)
}
}

// beforeRequest 会在请求到达服务器之前被调用,可以通过该函数对请求做最后一次修改
// isHttps 请求是否为https请求
// oreq 原始请求
// req hijackRequest修改后的请求
// 返回值: 修改后的请求,如果没有返回值则使用hijackRequest修改后的请求
beforeRequest = func(ishttps /*bool*/, oreq /*[]byte*/, req/*[]byte*/){
if str.Contains(req, `example.com`) {
newReq := poc.ReplaceHTTPPacketHeader(
req,
"X-Before-Request",
"Modified by beforeRequest",
)
return newReq
}
}
```

- **妙用 \- 处理前端加密通信**

在现代Web应用中,前端JavaScript经常对敏感数据进行加密后再与服务器通信,这导致Yakit MITM直接抓取到的是加密后的密文,用户无法直观地查看和修改请求内容。通过巧妙运用`hijackHTTPRequest`和`beforeRequest`的组合,可以完美解决这一问题。

具体实现思路是:在`hijackHTTPRequest`阶段对加密的请求体进行解密,将明文内容展示给用户进行修改;用户完成修改后,在`beforeRequest`阶段将修改后的明文重新加密,确保服务器接收到正确格式的加密数据。这种方式实现了"解密\-修改\-重加密"的完整流程,让用户能够透明地处理加密通信,既保持了与服务器的兼容性,又提供了良好的用户体验。

图:加密请求劫持处理流程

  • afterRequest - 响应最终修改钩子

    • 触发时机: 在响应即将发送回客户端的最后时刻被调用,位于 hijackHTTPResponse/hijackHTTPResponseEx 处理完成之后。这是对响应进行最终修改的机会,确保所有修改都能在响应真正返回给客户端前生效。

    • 功能说明: 允许用户对经过 hijackHTTPResponse/hijackHTTPResponseEx 处理后的响应进行最后一次检查和修改。该函数提供了完整的上下文信息,包括原始请求(oreq)、hijack修改后的请求(req)、原始响应(orsp)和hijack修改后的响应(rsp),用户可以基于这些信息来决定是否需要进一步修改响应。与hijackHTTPResponse不同的是,afterRequest通过返回值来提交修改后的响应,如果没有返回值则使用hijack阶段修改后的响应。

    • 使用说明: 这个钩子函数是响应处理链的最后一环,它可以直接获取到hijackHTTPResponse处理后的结果,允许用户统一对所有响应做最终调整。重要特性:这一步的修改同样对用户不可见 - 如果用户触发手动劫持查看响应,在劫持界面看到的内容是afterRequest处理之前的状态,而afterRequest的修改会在响应最终返回客户端前才被应用。这意味着afterRequest中的修改不会影响用户劫持时的响应查看界面,常用于添加全局性的响应头、统一的安全策略、内容过滤、或者不希望用户感知到的底层调整,确保响应的完整性和安全性。

有了beforeRequest做基础,我们理解afterRequest就轻松很多,接下来按我们说明的内容,将会做一系列操作,帮助用户理解整个热加载劫持过程。

图:Yakit HTTP响应劫持代码模板与效果演示

  • **妙用 - 处理前端加密通信:**在现代Web应用的响应处理中,服务器经常返回加密或编码后的敏感数据,这导致Yakit MITM直接抓取到的响应内容对用户来说是不可读的密文。通过巧妙运用hijackHTTPResponse和afterRequest的组合,可以完美解决这一问题。具体实现思路是:在hijackHTTPResponse阶段对加密的响应体进行解密,将明文内容展示给用户进行查看和修改;用户完成查看后,在afterRequest阶段将可能被修改的明文重新加密,确保客户端接收到正确格式的加密数据。这种方式实现了"解密-展示-重加密"的完整流程,让用户能够透明地处理加密响应,既保持了与客户端的兼容性,又提供了良好的调试和分析体验。特别适用于分析移动应用API、加密的JSON数据传输、以及需要动态内容替换的场景。

注意: beforeRequest 和 afterRequest 作为最终修改钩子,它们的执行优先级最高,会在对应的hijack函数执行完毕后被调用。这两个函数通过返回值机制来提交修改,与hijack系列函数的forward机制不同,用户需要注意这种差异以避免逻辑混乱。hijackHTTPRequest ``/ ``beforeRequesthijackHTTPResponse ``/ ``afterRequest这两套核心函数会在我们的实战章节中起非常大的作用,用户可以在后续章节中多次见到他们。

修改存储过程

存储处理类钩子函数专门用于在HTTP流量存储到数据库之前进行最后的处理和定制化操作。这个阶段只有一个核心函数:hijackSaveHTTPFlow,它为用户提供了强大的流量存储自定义能力。

hijackSaveHTTPFlow - 流量存储前处理钩子

  • 触发时机:在HTTP请求响应完整处理完成后,即将存储到History数据库之前触发。这是流量处理链的最后一个环节,所有的请求响应修改都已完成。

  • 功能说明:允许用户在流量入库前对流量数据进行最终的处理和标记,包括修改请求响应内容、添加标签、设置颜色标记。这个函数接收完整的流量结构体,用户可以访问和修改入库(保存到数据库)流量的所有属性。

  • 使用说明:该函数主要用于流量的后处理和分类标记,常见应用场景包括:

    1. 敏感信息标记:检测包含敏感关键字的流量并染色标记

    2. 数据解密存储:对加密的通信内容进行解密后存储明文

    3. 流量过滤:根据特定条件丢弃无关流量,减少存储空间占用

    4. 自动化标签:根据URL模式、响应状态等自动添加分类标签

为了更好地理解 hijackSaveHTTPFlow 函数的实际效果,我们通过一个具体的操作示例来演示其工作机制。在这个例子中,我们将编写一个简单的钩子函数,当检测到访问 example.com 域名的请求时,自动将该流量标记为红色,以便在流量历史记录中快速识别和定位。

图:Yakit 修改存储过程代码模板界面

途中涉及到的热加载代码如下:

// hijackSaveHTTPFlow 会在流量被存储到数据库前被调用,可以通过该函数对入库前的流量进行修改,例如修改请求/响应,添加tag/染色等
// flow 流量结构体,可以通过鼠标悬浮提示查看其拥有的字段并对其进行修改
// modify(modified) 提交修改后的流量结构体,如果未被调用,则使用原始的流量结构体
// drop() 丢弃流量
hijackSaveHTTPFlow = func(flow /* *yakit.HTTPFlow */, modify /* func(modified *yakit.HTTPFlow) */, drop/* func() */) {
if flow.Url.Contains("example.com") {
flow.Red()
modify(flow)
}
}

从上图可以清楚地看到 hijackSaveHTTPFlow 函数的完整工作流程:

  1. 代码编写阶段:在热加载代码编辑器中,我们实现了一个简洁的 hijackSaveHTTPFlow 函数,当流量URL包含 "example.com" 时,调用 flow.Red() 将流量染成红色,然后通过 modify(flow) 提交修改。

  2. 流量捕获阶段:当用户访问 http://www.example.com/ 时,该请求被Yakit成功捕获,可以在右侧面板中看到完整的请求和响应详情。

  3. 自动标记效果:最关键的是,在左侧的流量列表中可以看到,ID为54293的这条流量记录已经被自动染成了红色背景,这正是我们的 hijackSaveHTTPFlow 函数发挥作用的结果。

这个例子完美展示了存储处理类钩子函数的核心价值:它能够在流量入库前自动执行用户定义的逻辑,实现流量的智能分类和标记,让安全分析人员能够快速识别和定位关键流量,大大提高了渗透测试和安全审计的工作效率。通过这种自动化的流量处理机制,用户无需手动逐条检查流量记录,系统会根据预设规则自动完成分类标记工作。

在使用 hijackSaveHTTPFlow 函数时,核心的数据结构就是 flow 参数,它是一个 HTTPFlow 结构体实例。为了帮助开发者更好地理解和使用这个结构体,下面详细列出了 HTTPFlow 的所有字段和方法,用户可以根据自己的实际需求来使用下面的材料。

字段列表

方法列表