基于mitmproxy實現(xiàn)web被動掃描代理

mitmproxy模塊提供的使用方式是使用命令行來開一個代理,這里用python代碼調(diào)用mitmproxy的方法,開一個代理,獲取請求信息,并添加到隊列中,供后續(xù)掃描使用。

本文使用的環(huán)境:

Python 3.7.0
mitmproxy 5.2

安裝

安裝:pip install mitmproxy。依賴多,國內(nèi)安裝慢,建議用國內(nèi)鏡像來安裝:pip install -i https://mirrors.aliyun.com/pypi/simple/ mitmproxy

啟動代理

可以直接用:

from mitmproxy.tools.main import mitmdump
mitmdump(args="--listen-port=6666 -m upstream:127.0.0.1:8080 --proxyauth=root:root".split(" "))

來啟動代理,args參數(shù)跟調(diào)用mitmdump命令時傳的參數(shù)一樣。因為起初在網(wǎng)上搜,搜到的是另一段代碼,所以沒用這種簡潔的方式,用的是:

#!/usr/bin/python3
# -*-coding:utf-8-*-

import time
import queue
from multiprocessing import Process, freeze_support, Queue

from mitmproxy import proxy, options
from mitmproxy.http import HTTPFlow
from mitmproxy.tools.dump import DumpMaster


class Handler:
    """
    將請求加入隊列
    """
    def __init__(self, req_queue: Queue):
        self.req_queue = req_queue

    def request(self, flow: HTTPFlow):
        request_dict = {
            "method": flow.request.method,
            "url": flow.request.url,
            "headers": [(key, flow.request.headers[key]) for key in flow.request.headers],
            "cookies": [(key, flow.request.cookies[key]) for key in flow.request.cookies],
            "data": flow.request.text
        }
        try:
            print(request_dict.get("url"))
            self.req_queue.put(request_dict, timeout=2)
        except queue.Full:
            pass

    def response(self, flow: HTTPFlow):
        pass

    def responseheaders(self, flow: HTTPFlow):
       pass


def do_start_proxy(req_queue):
    opts = options.Options(listen_host="127.0.0.1", listen_port=6666)

    m = DumpMaster(opts, with_termlog=False, with_dumper=False)

    pconf = proxy.config.ProxyConfig(opts)
    m.server = proxy.server.ProxyServer(pconf)
    m.addons.add(Handler(req_queue))

    print("Proxy server listening at http://127.0.0.1:6666")
    m.run()
    # m.shutdown()


def start_proxy(req_queue):
    freeze_support()
    p = Process(target=do_start_proxy, args=(req_queue, ))
    p.start()
    return p


if __name__ == "__main__":
    req_queue = Queue(6000)
    p = start_proxy(req_queue)
    try:
        while True:
            # 從req_queue獲取請求,進行處理
            time.sleep(300)
    except KeyboardInterrupt:
        p.terminate()
        p.join()

下文將以這種方式來說明

插件編寫

上面使用子進程啟動mitmproxy,然后通過m.addons.add(Handler(req_queue))注冊插件,該插件將收到的請求信息添加到隊列中,以便后續(xù)使用。

Handler類就是插件。其request方法在mitmproxy接到請求后調(diào)用,response方法在收到響應(yīng)后調(diào)用,responseheaders方法在收到響應(yīng)頭部時就調(diào)用.(更多的回調(diào)方法參考這里)。這些回調(diào)方法,通常接收一個flow參數(shù),可以用來獲取請求和響應(yīng)信息,使用也簡單,看這里就行。

注意: 不要在request()里用到flow.response,否則會卡住

HTTPS證書

mitmproxy已經(jīng)處理好證書了。將瀏覽器代理指向mitmproxy,訪問mitm.it,下載安裝證書就行

option配置

上面那段代碼中:

    opts = options.Options(listen_host="127.0.0.1", listen_port=6666)

    m = DumpMaster(opts, with_termlog=False, with_dumper=False)

    pconf = proxy.config.ProxyConfig(opts)
    m.server = proxy.server.ProxyServer(pconf)
    m.addons.add(Handler(req_queue))

listen_host配置代理監(jiān)聽地址,listen_port配置代理監(jiān)聽端口。with_templog為True時會輸出客戶端連接、斷開信息,如:127.0.0.1:53033: clientconnect 127.0.0.1:53034: clientconnect;with_dumper為True時,輸出連接信息:請求方法、URL、狀態(tài)碼等。所有可配置的option,看這里。

舉兩個其它的配置:

配置上流代理(mitmproxy的流量都傳到這個proxy):

opts.update(mode="upstream:127.0.0.1:1080")  # 所有接收到流量都傳到127.0.0.1:1080這個代理去
opts.update(ssl_insecure=True)  # 不驗證上流代理給的https證書

配置代理的賬號密碼:

opts.update(proxyauth="root:root")

這句代碼要在初始化DumpMaster類后再調(diào)用。因為這個配置選項是由內(nèi)置插件ProxyAuth提供的,該插件在初始化DumpMaster類時添加。

總結(jié)

感覺直接調(diào)用mitmdump函數(shù)簡單些。一開始用的是網(wǎng)上給的,沒看源碼,不知道有這種方式。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容