FiddlerScript / Burp Extensions Python API:如何编写自定义代理规则,对 HTTP/HTTPS 流量进行自动化过滤、修改和重放?

各位老铁,大家好!今天咱们来聊聊如何用 FiddlerScript 和 Burp Extensions Python API,打造属于你自己的代理规则,玩转 HTTP/HTTPS 流量的过滤、修改和重放。

咱们先来热热身,简单了解一下这俩工具的特性。

FiddlerScript:拦截、修改、重定向,一条龙服务

FiddlerScript 是 Fiddler 自带的脚本语言,基于 JScript.NET。它主要通过事件处理函数来工作,比如 OnBeforeRequest(请求发送前)和 OnBeforeResponse(响应返回前)。你可以用它来:

  • 拦截请求/响应: 阻止某些请求发送出去,或者阻止某些响应返回给客户端。
  • 修改请求/响应: 修改请求的 URL、Headers、Body,或者修改响应的 Status Code、Headers、Body。
  • 重定向请求: 将请求转发到其他服务器。

FiddlerScript 的优点是简单易用,上手快。缺点是功能相对有限,扩展性不如 Burp Extensions。

Burp Extensions Python API:灵活、强大,定制化利器

Burp Extensions 允许你用 Python、Java、Ruby 等语言编写插件,扩展 Burp Suite 的功能。Python API 提供了丰富的接口,让你能够:

  • 监听 HTTP 流量: 获取所有经过 Burp Suite 的 HTTP/HTTPS 请求和响应。
  • 修改请求/响应: 像 FiddlerScript 一样,修改请求的 URL、Headers、Body 等。
  • 执行主动扫描: 自动检测 Web 应用的漏洞。
  • 自定义 UI: 添加新的选项卡、按钮、表格等,增强 Burp Suite 的交互性。

Burp Extensions 的优点是功能强大,扩展性强,可以定制各种复杂的规则。缺点是学习曲线相对陡峭,需要一定的编程基础。

开胃小菜:FiddlerScript 拦截指定 URL

咱们先从 FiddlerScript 入手,来个简单的例子:拦截所有访问 example.com 的请求。

打开 Fiddler,按下 Shift + Ctrl + J,打开 FiddlerScript 编辑器。找到 OnBeforeRequest 函数,添加以下代码:

if (oSession.uriContains("example.com")) {
    oSession.oFlags["x-breakrequest"] = "Stop"; // 停止请求
    oSession["ui-backcolor"] = "red";         // 标记为红色,方便识别
}

这段代码的意思是:如果请求的 URL 包含 example.com,就停止请求,并把会话的背景色设置为红色。

保存脚本,Fiddler 就会拦截所有访问 example.com 的请求。

正餐来了:Burp Extensions Python API 修改 User-Agent

接下来,咱们用 Burp Extensions Python API 来修改 User-Agent。

首先,确保你安装了 Jython。然后在 Burp Suite 中,选择 "Extender" -> "Extensions" -> "Add"。选择 "Extension type" 为 "Python",然后选择你的 Python 脚本文件。

下面是 Python 脚本的代码:

from burp import IBurpExtender
from burp import IHttpListener
from burp import IRequestInfo
from burp import IResponseInfo
from burp import IHttpService

class BurpExtender(IBurpExtender, IHttpListener):

    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("User-Agent Modifier")

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

        print "User-Agent Modifier loaded"
        return

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        # only process requests
        if messageIsRequest:

            # get the HTTP service for the request
            httpService = messageInfo.getHttpService()

            # get the request
            request = messageInfo.getRequest()

            # get request information
            requestInfo = self._helpers.analyzeRequest(httpService, request)

            # get headers
            headers = requestInfo.getHeaders()

            # modify the User-Agent header
            new_headers = []
            user_agent_found = False
            for header in headers:
                if header.startswith("User-Agent:"):
                    new_headers.append("User-Agent: My Custom User-Agent")
                    user_agent_found = True
                else:
                    new_headers.append(header)

            if not user_agent_found:
                new_headers.append("User-Agent: My Custom User-Agent")

            # rebuild the request
            body = request[requestInfo.getBodyOffset():]
            new_request = self._helpers.buildHttpMessage(new_headers, body)

            # update the request
            messageInfo.setRequest(new_request)

这段代码实现了 IBurpExtenderIHttpListener 接口。registerExtenderCallbacks 函数用于注册扩展,processHttpMessage 函数用于处理 HTTP 消息。

processHttpMessage 函数中,我们首先判断消息是否是请求。如果是请求,我们就获取请求的 Headers,然后修改 User-Agent Header。最后,我们用修改后的 Headers 和 Body 重新构建请求,并更新消息。

把这个脚本加载到 Burp Suite 中,以后所有经过 Burp Suite 的请求的 User-Agent 都会被修改为 "My Custom User-Agent"。

进阶技巧:FiddlerScript 模拟特定浏览器

有时候,我们需要模拟特定浏览器的行为,比如爬虫或者兼容性测试。FiddlerScript 也可以做到这一点。

if (oSession.uriContains("target.com")) {
    oSession.oRequest["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"; // 模拟 Chrome
    oSession.oRequest["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9";
    oSession.oRequest["Accept-Language"] = "zh-CN,zh;q=0.9,en;q=0.8";
}

这段代码的意思是:如果请求的 URL 包含 target.com,就修改请求的 User-Agent、Accept 和 Accept-Language Header,模拟 Chrome 浏览器的行为。

高级用法:Burp Extensions Python API 重放请求

Burp Extensions Python API 可以用来重放请求,模拟各种攻击场景。

from burp import IBurpExtender
from burp import IContextMenuFactory
from javax.swing import JMenuItem
from java.util import List, ArrayList
from java.net import URL

class BurpExtender(IBurpExtender, IContextMenuFactory):

    def registerExtenderCallbacks(self, callbacks):
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Replay Request")
        callbacks.registerContextMenuFactory(self)
        return

    def createMenuItems(self, invocation):
        menuList = ArrayList()
        menuItem = JMenuItem("Replay Request", actionPerformed=self.replayRequest)
        menuList.add(menuItem)
        self._invocation = invocation
        return menuList

    def replayRequest(self, event):
        messages = self._invocation.getSelectedMessages()
        for messageInfo in messages:
            request = messageInfo.getRequest()
            httpService = messageInfo.getHttpService()
            host = httpService.getHost()
            port = httpService.getPort()
            protocol = httpService.getProtocol()

            # Construct URL
            url = URL(protocol, host, port, "")
            requestInfo = self._helpers.analyzeRequest(httpService, request)
            path = requestInfo.getUrl().getPath()
            url = URL(protocol, host, port, path) # Append path

            # Replay the request
            self._callbacks.makeHttpRequest(
                httpService.getHost(),
                httpService.getPort(),
                httpService.getProtocol() == "https",
                request
            )

这段代码添加了一个右键菜单项 "Replay Request",当你选中一个请求,点击这个菜单项时,就会重放这个请求。

实战案例:FiddlerScript 拦截并替换图片

很多时候,我们想替换网页中的图片,比如把广告图片替换成其他图片,或者把低分辨率图片替换成高分辨率图片。FiddlerScript 可以轻松实现这个功能。

if (oSession.uriContains(".jpg") || oSession.uriContains(".png") || oSession.uriContains(".gif")) {
    if (oSession.url.EndsWith(".jpg") || oSession.url.EndsWith(".png") || oSession.url.EndsWith(".gif"))
    {
        oSession.utilDecodeResponse(); // 解码响应
        oSession.ResponseBody = System.IO.File.ReadAllBytes("C:\path\to\your\image.png"); // 替换图片
        oSession.ResponseHeaders["Content-Type"] = "image/png"; // 修改 Content-Type
    }
}

这段代码的意思是:如果请求的 URL 包含 .jpg.png.gif,就替换响应的 Body 为本地图片文件,并修改 Content-Type Header。

高级实战:Burp Extensions Python API 自动修改 Cookie

Cookie 是 Web 应用中常用的身份验证机制。有时候,我们需要修改 Cookie,比如模拟其他用户的身份,或者绕过某些验证机制。Burp Extensions Python API 可以帮助我们自动化这个过程。

from burp import IBurpExtender
from burp import IHttpListener

class BurpExtender(IBurpExtender, IHttpListener):

    def registerExtenderCallbacks(self, callbacks):
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()
        callbacks.setExtensionName("Cookie Modifier")
        callbacks.registerHttpListener(self)
        return

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if messageIsRequest:
            request = messageInfo.getRequest()
            requestInfo = self._helpers.analyzeRequest(messageInfo.getHttpService(), request)
            headers = requestInfo.getHeaders()

            new_headers = []
            cookie_found = False
            for header in headers:
                if header.startswith("Cookie:"):
                    # Modify the cookie here.  Replace "old_cookie" with your cookie's name
                    # and "new_value" with the new value you want to set.
                    new_headers.append("Cookie: old_cookie=new_value")
                    cookie_found = True
                else:
                    new_headers.append(header)

            if not cookie_found:
                new_headers.append("Cookie: old_cookie=new_value")

            body = request[requestInfo.getBodyOffset():]
            new_request = self._helpers.buildHttpMessage(new_headers, body)
            messageInfo.setRequest(new_request)

这段代码修改了请求中的 Cookie 值。 你需要将 old_cookie 替换为你要修改的 Cookie 的名称,并将 new_value 替换为你要设置的新值。

实用规则速查表

功能 FiddlerScript Burp Extensions Python API
拦截请求 oSession.oFlags["x-breakrequest"] = "Stop"; 不直接拦截,但可以修改请求使其无效,或直接丢弃。
修改请求 Header oSession.oRequest["Header-Name"] = "New Value"; 获取请求 Headers,修改后重新构建请求。
修改请求 Body oSession.utilDecodeRequest(); oSession.RequestBody = System.Text.Encoding.UTF8.GetBytes("New Body"); 获取请求 Body,修改后重新构建请求。
修改响应 Header oSession.oResponse["Header-Name"] = "New Value"; 获取响应 Headers,修改后重新构建响应。
修改响应 Body oSession.utilDecodeResponse(); oSession.ResponseBody = System.Text.Encoding.UTF8.GetBytes("New Body"); 获取响应 Body,修改后重新构建响应。
重定向请求 oSession.fullUrl = "http://example.com"; 可以修改请求的 URL,达到重定向的效果。
模拟浏览器 修改 User-Agent, Accept, Accept-Language 等 Header。 同上。
重放请求 需要使用 Fiddler 的 Composer 功能手动重放。 通过 callbacks.makeHttpRequest() 函数重放请求。
修改 Cookie oSession.oRequest["Cookie"] = "Cookie-Name=New Value"; (需要处理已存在的 Cookie) 获取请求 Headers,找到 Cookie Header,修改后重新构建请求。
替换图片 oSession.utilDecodeResponse(); oSession.ResponseBody = System.IO.File.ReadAllBytes("C:\path\to\your\image.png"); oSession.ResponseHeaders["Content-Type"] = "image/png"; 获取响应 Body,替换为新的图片数据,并修改 Content-Type Header。

注意事项

  • 编码问题: 在处理 Body 时,要注意编码问题,确保编码一致。
  • 性能问题: 复杂的规则可能会影响 Fiddler 和 Burp Suite 的性能,要注意优化代码。
  • HTTPS 问题: Fiddler 和 Burp Suite 需要配置 HTTPS 代理,才能拦截和修改 HTTPS 流量。
  • Burp Suite Pro: 某些Burp Suite的高级功能(例如Scanner,Intruder)需要Pro版本。

总结

FiddlerScript 和 Burp Extensions Python API 都是强大的工具,可以帮助我们自动化过滤、修改和重放 HTTP/HTTPS 流量。FiddlerScript 简单易用,适合快速开发一些简单的规则。Burp Extensions Python API 功能强大,扩展性强,适合开发复杂的、定制化的规则。

希望今天的讲座对大家有所帮助! 记住,实践才是检验真理的唯一标准,多动手,多尝试,你也能成为流量操控大师! 溜了溜了!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注