第四章 指紋識別(三)
作者:Justin Hutchens
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
4.13 SNMPwalk SNMP 分析
SNMPwalk 是個更加復(fù)雜的 SNMP 掃描器,可以通過猜測 SNMP 團(tuán)體字符串來收集來自設(shè)備的大量信息。SNMPwalk 循環(huán)遍歷一系列請求來收集來自設(shè)備的盡可能多的信息。
準(zhǔn)備
為了使用 SNMPwalk 來執(zhí)行操作系統(tǒng)識別,你需要擁有開啟 SNMP 并可以探測的遠(yuǎn)程系統(tǒng)。提供的例子使用 Windows XP。配置 Windows 系統(tǒng)的更多信息請參考第一章的“安裝 Windows Server”秘籍。
操作步驟
為了執(zhí)行 SNMPwalk,應(yīng)該將一系列參數(shù)傳給工具,包括被分析系統(tǒng)的 IP 地址,所使用的團(tuán)體字符串,以及系統(tǒng)所使用的 SNMP 版本:
root@KaliLinux:~# snmpwalk 172.16.36.134 -c public -v 2c
iso.3.6.1.2.1.1.1.0 = STRING: "Hardware: x86 Family 6 Model 58 Stepping 9 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Uniprocessor Free)"
iso.3.6.1.2.1.1.2.0 = OID:
iso.3.6.1.4.1.311.1.1.3.1.1
iso.3.6.1.2.1.1.3.0 = Timeticks: (56225) 0:09:22.25
iso.3.6.1.2.1.1.4.0 = ""
iso.3.6.1.2.1.1.5.0 = STRING: "DEMO-72E8F41CA4"
iso.3.6.1.2.1.1.6.0 = ""
iso.3.6.1.2.1.1.7.0 = INTEGER: 76
iso.3.6.1.2.1.2.1.0 = INTEGER: 2
iso.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
iso.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2
iso.3.6.1.2.1.2.2.1.2.1 = Hex-STRING: 4D 53 20 54 43 50 20 4C 6F 6F 70 62 61 63 6B 20 69 6E 74 65 72 66 61 63 65 00
iso.3.6.1.2.1.2.2.1.2.2 = Hex-STRING: 41 4D 44 20 50 43 4E 45 54 20 46 61 6D 69 6C 79
為了對開啟 SNMP 的 Windows XP 系統(tǒng)使用 SNMPwalk,我們使用默認(rèn)的團(tuán)體字符串public,以及版本2c。這會生成大量數(shù)據(jù),在展示中已經(jīng)截?cái)唷R⒁?,通常所有被識別的信息都在所查詢的 IOD 值后面。這個數(shù)據(jù)可以通過使用管道連接到cut函數(shù)來移除標(biāo)識符。
root@KaliLinux:~# snmpwalk 172.16.36.134 -c public -v 2c | cut -d "=" -f 2
STRING: "Hardware: x86 Family 6 Model 58 Stepping 9 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Uniprocessor Free)"
OID: iso.3.6.1.4.1.311.1.1.3.1.1
Timeticks: (75376) 0:12:33.76
""
STRING: "DEMO-72E8F41CA4"
要注意, SNMPwalk 的輸出中不僅僅提供了系統(tǒng)標(biāo)識符。在輸出中,可以看到一些明顯的信息,另一些信息則是模糊的。但是,通過徹底分析它,你可以收集到目標(biāo)系統(tǒng)的大量信息:
Hex-STRING: 00 50 56 FF 2A 8E
Hex-STRING: 00 0C 29 09 C3 79
Hex-STRING: 00 50 56 F0 EE E8
IpAddress: 172.16.36.2
IpAddress: 172.16.36.180
IpAddress: 172.16.36.254
在輸出的一部分中,可以看到十六進(jìn)制值和 IP 地址的列表。通過參考已知系統(tǒng)的網(wǎng)絡(luò)接口,我們就可以知道,這些是 ARP 緩存的內(nèi)容。它表明了儲存在設(shè)備中的 IP 和 MAC 地址的關(guān)聯(lián)。
STRING: "FreeSSHDService.exe"
STRING: "vmtoolsd.exe"
STRING: "java.exe"
STRING: "postgres.exe"
STRING: "java.exe"
STRING: "java.exe"
STRING: "TPAutoConnSvc.exe"
STRING: "snmp.exe"
STRING: "snmptrap.exe"
STRING: "TPAutoConnect.exe"
STRING: "alg.exe"
STRING: "cmd.exe"
STRING: "postgres.exe"
STRING: "freeSSHd 1.2.0"
STRING: "CesarFTP 0.99g"
STRING: "VMware Tools"
STRING: "Python 2.7.1"
STRING: "WebFldrs XP"
STRING: "VMware Tools"
此外,運(yùn)行進(jìn)程和安裝的應(yīng)用的列表可以在輸出中找到。這個信息在枚舉運(yùn)行在目標(biāo)系統(tǒng)的服務(wù),以及識別潛在的可利用漏洞時十分有用。
工作原理
不像 Onesixtyone,SNMPwalk 不僅僅能夠識別默認(rèn) SNMP 團(tuán)體字符串的使用,也可以利用這個配置來收集大量來自目標(biāo)系統(tǒng)的信息。這可以通過使用一序列 SNMP GETNEXT 請求,并使用請求來爆破系統(tǒng)的所有可用信息來完成。
4.14 Scapy 防火墻識別
通過評估從封包注入返回響應(yīng),我們就可以判斷遠(yuǎn)程端口是否被防火墻設(shè)備過濾。為了對這個過程如何工作有個徹底的認(rèn)識,我們可以使用 Scapy 在封包級別執(zhí)行這個任務(wù)。
準(zhǔn)備
為了使用 Scapy 來執(zhí)行防火墻識別,你需要運(yùn)行網(wǎng)絡(luò)服務(wù)的遠(yuǎn)程系統(tǒng)。此外,你需要實(shí)現(xiàn)一些過濾機(jī)制。這可以使用獨(dú)立防火墻設(shè)備,或者基于主機(jī)的過濾,例如 Windows 防火墻來完成。通過操作防火墻設(shè)備的過濾設(shè)置,你應(yīng)該能夠修改被注入封包的響應(yīng)。
操作步驟
為了高效判斷是否 TCP 端口被過濾,需要向目標(biāo)端口發(fā)送 TCP SYN 和 ACK 封包?;谟糜陧憫?yīng)這些注入的封包,我們可以判斷端口是否多慮。這兩個封包的注入可能會產(chǎn)生四種不同的響應(yīng)組合。我們會討論每一種場景,它們對于目標(biāo)端口的過濾來說表示什么,以及如何測試它們。這四個可能的響應(yīng)組合如下:
- SYN 請求沒有響應(yīng),ACK 請求收到 RST 響應(yīng)。
- SYN 請求收到 SYN+ACK 或者 SYN+RST 響應(yīng),ACK 請求沒有響應(yīng)。
- SYN 請求收到 SYN+ACK 或者 SYN+RST 響應(yīng),ACK 請求收到 RST 響應(yīng)。
- SYN 和 ACK 請求都沒有響應(yīng)。
| | SYN | ACK | |
| --- | --- |
| 1 | 無響應(yīng) | RST | 狀態(tài)過濾,禁止連入 |
| 2 | SYN + ACK/RST | 無響應(yīng) | 狀態(tài)過濾,禁止連出 |
| 3 | SYN + ACK/RST | RST | 無過濾,SYN 收到 ACK 則開放,反之關(guān)閉 |
| 4 | 無響應(yīng) | 無響應(yīng) | 無狀態(tài)過濾 |
在第一種場景中,我們應(yīng)該考慮 SYN 請求沒有響應(yīng),ACK 請求收到 RST 響應(yīng)的配置。為了測試它,我們首先應(yīng)該發(fā)送 TCP ACK 封包給目標(biāo)端口。為了發(fā)送 TCP ACK 封包給任何給定的端口,我們首先必須構(gòu)建請求的層級,我們首先需要構(gòu)建 IP 層:
root@KaliLinux:~# scapy Welcome to Scapy (2.2.0)
>>> i = IP()
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
>>> i.dst = "172.16.36.135"
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
為了構(gòu)建請求的 IP 層,我們需要將IP對象賦給變量i。通過調(diào)用display函數(shù),我們可以確定對象的屬性配置。通常,發(fā)送和接受地址都設(shè)為回送地址,127.0.0.1。這些值可以通過修改目標(biāo)地址來修改,也就是設(shè)置i.dst為想要掃描的地址的字符串值。通過再次調(diào)用dislay函數(shù),我們看到不僅僅更新的目標(biāo)地址,也自動更新了和默認(rèn)接口相關(guān)的源 IP 地址。現(xiàn)在我們構(gòu)建了請求的 IP 層,我們可以構(gòu)建 TCP 層了。
>>> t = TCP()
>>> t.display()
###[ TCP ]###
sport= ftp_data
dport= http
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= S
window= 8192
chksum= None
urgptr= 0
options= {}
>>> t.dport = 22
>>> t.flags = 'A'
>>> t.display()
###[ TCP ]###
sport= ftp_data
dport= ssh
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= A
window= 8192
chksum= None
urgptr= 0
options= {}
為了構(gòu)建請求的 TCP 層,我們使用和 IP 層相同的技巧。在這個立即中,TCP對象賦給了t變量。像之前提到的那樣,默認(rèn)的配置可以通過調(diào)用display函數(shù)來確定。這里我們可以看到目標(biāo)端口的默認(rèn)值為 HTTP 端口 80。對于我們的首次掃描,我們將 TCP 設(shè)置保留默認(rèn)。現(xiàn)在我們創(chuàng)建了 TCP 和 IP 層,我們需要將它們疊放來構(gòu)造請求。
>>> request = (i/t)
>>> request.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= tcp
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
###[ TCP ]###
sport= ftp_data
dport= ssh
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= A
window= 8192
chksum= None
urgptr= 0
options= {}
我們可以通過以斜杠分離變量來疊放 IP 和 TCP 層。這些層面之后賦給了新的變量,它代表整個請求。我們之后可以調(diào)用dispaly函數(shù)來查看請求的配置。一旦構(gòu)建了請求,可以將其傳遞給sr1函數(shù)來分析響應(yīng):
>>> response = sr1(request,timeout=1)
..Begin emission:
.........Finished to send 1 packets.
....*
Received 16 packets, got 1 answers, remaining 0 packets
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 40
id= 0
flags= DF
frag= 0L
ttl= 63
proto= tcp
chksum= 0x9974
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ TCP ]###
sport= ssh
dport= ftp_data
seq= 0
ack= 0
dataofs= 5L
reserved= 0L
flags= R
window= 0
chksum= 0xe5b
urgptr= 0
options= {}
###[ Padding ]###
load= '\x00\x00\x00\x00\x00\x00'
相同的請求可以不通過構(gòu)建和堆疊每一層來執(zhí)行。反之,我們使用單獨(dú)的一條命令,通過直接調(diào)用函數(shù)并傳遞合適的參數(shù):
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1)
..Begin emission:
........Finished to send 1 packets.
....*
Received 15 packets, got 1 answers, remaining 0 packets
>>> response
<IP version=4L ihl=5L tos=0x0 len=40 id=0 flags=DF frag=0L ttl=63 proto=tcp chksum=0x9974 src=172.16.36.135 dst=172.16.36.180 options=[] |<TCP sport=ssh dport=ftp_data seq=0 ack=0 dataofs=5L reserved=0L flags=R window=0 chksum=0xe5b urgptr=0 |<Padding load='\x00\x00\x00\x00\x00\x00' |>>>
要注意在這個特定場景中,注入的 ACK 封包的響應(yīng)是 RST 封包。測試的下一步就是以相同方式注入 SYN 封包。
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =1)
Begin emission:
Finished to send 1 packets.
Received 9 packets, got 0 answers, remaining 1 packets
以相同方式發(fā)送 SYN 請求之后,沒有收到任何響應(yīng),并且函數(shù)在超時時間達(dá)到只有斷開了連接。這個響應(yīng)組合表明發(fā)生了狀態(tài)包過濾。套接字通過丟掉 SYN 請求拒絕了所有入境的連接,但是沒有過濾 ACK 封包來確保仍舊存在出境連接和持續(xù)中的通信。這個響應(yīng)組合可以在 Python 中測試來確認(rèn)狀態(tài)過濾的端口:
root@KaliLinux:~# python
Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
>>> ACK_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose =0)
>>> SYN_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =0)
>>> if ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
... print "Stateful filtering in place"
... Stateful filtering in place
>>> exit()
在使用 Scapy 生成每個請求之后,測試可以用于評估這些響應(yīng),來判斷是否 ACK 或者 SYN(但不是全部)請求接受到了響應(yīng)。這個測試對于識別該場景以及下一個場景十分高效,其中 SYN 注入而不是 ACK 注入接受到了響應(yīng)。
SYN 注入收到了 SYN+ACK 或者 RST+ACK 響應(yīng),但是 ACK 注入沒有收到響應(yīng)的場景,也表明存在狀態(tài)過濾。剩余的測試也一樣。首先,向目標(biāo)端口發(fā)送 ACK 封包。
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose =1)
Begin emission:
Finished to send 1 packets.
Received 16 packets, got 0 answers, remaining 1 packets
在這個場景中可以執(zhí)行完全相同的測試,如果兩哥注入請求之一收到響應(yīng),測試就表明存在狀態(tài)過濾。
root@KaliLinux:~# python
Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
>>> ACK_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose =0)
>>> SYN_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =0)
>>> if ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
... print "Stateful filtering in place"
... Stateful filtering in place
>>> exit()
響應(yīng)的組合表明,狀態(tài)過濾執(zhí)行在 ACK 封包上,任何來自外部的符合上下文的 ACK 封包都會被丟棄。但是,入境連接嘗試的響應(yīng)表明,端口沒有完全過濾。
另一個可能的場景就是 SYN 和 ACK 注入都收到了預(yù)期響應(yīng)。這種情況下,沒有任何形式的過濾。為了對這種情況執(zhí)行測試,我們首先執(zhí)行 ACK 注入,之后分析響應(yīng):
>>> response =
sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose=1)
Begin emission:
Finished to send 1 packets.
Received 5 packets, got 1 answers, remaining 0 packets
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 40
id= 0
flags= DF
frag= 0L
ttl= 64
proto= tcp
chksum= 0x9974
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ TCP ]###
sport= ssh
dport= ftp_data
seq= 0
ack= 0
dataofs= 5L
reserved= 0L
flags= R
window= 0
chksum= 0xe5b
urgptr= 0
options= {}
###[ Padding ]###
load= '\x00\x00\x00\x00\x00\x00'
在封包未被過濾的情況下,來路不明的 ACK 封包發(fā)送給了目標(biāo)端口,并應(yīng)該產(chǎn)生返回的 RST 封包。這個 RST 封包表明,ACK 封包不符合上下文,并且打算斷開連接。發(fā)送了 ACK 注入之后,我們可以向相同端口發(fā)送 SYN 注入。
>>> response =
sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =1)
Begin emission:
Finished to send 1 packets.
Received 4 packets, got 1 answers, remaining 0 packets
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 44
id= 0
flags= DF
frag= 0L
ttl= 64
proto= tcp
chksum= 0x9970
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ TCP ]###
sport= ssh
dport= ftp_data
seq= 1147718450
ack= 1
dataofs= 6L
reserved= 0L
flags= SA
window= 5840
chksum= 0xd024
urgptr= 0
options= [('MSS', 1460)]
###[ Padding ]###
load= '\x00\x00'
>>> response[TCP].flags
18L
>>> int(response[TCP].flags)
18
在端口未過濾并打開的情況中,會返回 SYN+ACK 響應(yīng)。要注意 TCPflags屬性的實(shí)際值是個long變量,值為 18。這個值可以輕易使用int函數(shù)來轉(zhuǎn)換成int變量。這個 18 的值是 TCP 標(biāo)識位序列的十進(jìn)制值。SYN 標(biāo)志的十進(jìn)制值為 2,而 ACK 標(biāo)識的十進(jìn)制值為 16。假設(shè)這里沒有狀態(tài)過濾,我們可以通過評估 TCPflags值的整數(shù)轉(zhuǎn)換,在 Python 中測試端口是否未過濾并打開。
root@KaliLinux:~# python Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
>>> ACK_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose =0)
>>> SYN_response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =0)
>>> if ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
... print "Stateful filtering in place"
... elif int(SYN_response[TCP].flags) == 18:
... print "Port is unfiltered and open"
... elif int(SYN_response[TCP].flags) == 20:
... print "Port is unfiltered and closed"
... Port is unfiltered and open
>>> exit()
我們可以執(zhí)行相似的測試來判斷是否端口未過濾并關(guān)閉。未過濾的關(guān)閉端口會激活 RST 和 ACK 標(biāo)識。像之前那樣,ACK 標(biāo)識為整數(shù) 16,RST 標(biāo)識為 整數(shù) 4。所以,未過濾的關(guān)閉端口的 TCPflags值的整數(shù)轉(zhuǎn)換應(yīng)該是 20:
root@KaliLinux:~# python Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
>>> ACK_response = sr1(IP(dst="172.16.36.135")/TCP(dport=4444,flags='A'),timeout=1,verbo se=0)
>>> SYN_response = sr1(IP(dst="172.16.36.135")/TCP(dport=4444,flags='S'),timeout=1,verbo se=0)
>>> if ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
... print "Stateful filtering in place"
... elif int(SYN_response[TCP].flags) == 18:
... print "Port is unfiltered and open"
... elif int(SYN_response[TCP].flags) == 20:
... print "Port is unfiltered and closed"
... Port is unfiltered and closed
>>> exit()
最后,我們應(yīng)該考慮最后一種場景,其中 SYN 或者 ACK 注入都沒有收到響應(yīng)。這種場景中,每個sr1的實(shí)例都會在超時的時候斷開。
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='A'),timeout=1,verbose =1)
Begin emission:
Finished to send 1 packets.
Received 36 packets, got 0 answers, remaining 1 packets
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=22,flags='S'),timeout=1,verbose =1)
Begin emission:
Finished to send 1 packets.
Received 18 packets, got 0 answers, remaining 1 packets
每個注入封包都缺少響應(yīng),表明端口存在無狀態(tài)過濾,僅僅是丟棄所有入境的流量,無論狀態(tài)是什么?;蛘哌@表明遠(yuǎn)程系統(tǒng)崩潰了。我們的第一想法可能是,可以通過在之前的測試序列的末尾向else添加執(zhí)行流,在 Python 中測試它。理論上,如果任何注入都沒有接受到響應(yīng),else中的操作會執(zhí)行。簡單來說,else中的操作會在沒有接收到響應(yīng)的時候執(zhí)行。
root@KaliLinux:~# python Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from scapy.all import *
>>> ACK_response = sr1(IP(dst="172.16.36.135")/TCP(dport=4444,flags='A'),timeout=1,verbo se=0)
>>> SYN_response = sr1(IP(dst="172.16.36.135")/TCP(dport=4444,flags='S'),timeout=1,verbo se=0)
>>> if ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
... print "Stateful filtering in place"
... elif int(SYN_response[TCP].flags) == 18:
... print "Port is unfiltered and open"
... elif int(SYN_response[TCP].flags) == 20:
... print "Port is unfiltered and closed"
... else:
... print "Port is either unstatefully filtered or host is down"
...
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: 'NoneType' object has no attribute '__getitem__'
這意味著理論上可以生效,但是實(shí)際上并不工作。操作值為空的變量的時候,Python 實(shí)際上會產(chǎn)生錯誤。為了避免這種問題,首先就需要檢測沒有收到任何回復(fù)的情況。
>>> if (ACK_response == None) and (SYN_response == None):
... print "Port is either unstatefully filtered or host is down"
... Port is either unstatefully filtered or host is down
這個完成的測試序列之后可以集成到單個功能性腳本中。這個腳本接受兩個參數(shù),包括目標(biāo) IP 地址和被測試的端口。之后注入 ACK 和 SYN 封包,如果存在響應(yīng),響應(yīng)會儲存用于評估。之后執(zhí)行四個測試來判斷是否端口上存在過濾。一開始,會執(zhí)行測試來判斷是否沒有受到任何響應(yīng)。如果是這樣,輸出會表示遠(yuǎn)程主機(jī)崩潰了,或者端口存在無狀態(tài)過濾,并丟棄所有流量。如果接收到了任何請求,會執(zhí)行測試來判斷是否接受到了某個注入的響應(yīng),而不是全部。如果是這樣,輸出會表明端口存在狀態(tài)過濾。最后如果兩個注入都接受到了響應(yīng),端口會被識別為物過濾,并且會評估 TCP 標(biāo)志位來判斷端口開放還是關(guān)閉。
#!/usr/bin/python
import sys import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
if len(sys.argv) != 3:
print "Usage - ./ACK_FW_detect.py [Target-IP] [Target Port]"
print "Example - ./ACK_FW_detect.py 10.0.0.5 443"
print "Example will determine if filtering exists on port 443 of host 10.0.0.5"
sys.exit()
ip = sys.argv[1]
port = int(sys.argv[2])
ACK_response = sr1(IP(dst=ip)/TCP(dport=port,flags='A'),timeout=1,verbose=0)
SYN_response = sr1(IP(dst=ip)/TCP(dport=port,flags='S'),timeout=1,verbose=0)
if (ACK_response == None) and (SYN_response == None):
print "Port is either unstatefully filtered or host is down"
elif ((ACK_response == None) or (SYN_response == None)) and not ((ACK_response ==None) and (SYN_response == None)):
print "Stateful filtering in place"
elif int(SYN_response[TCP].flags) == 18:
print "Port is unfiltered and open"
elif int(SYN_response[TCP].flags) == 20:
print "Port is unfiltered and closed"
else:
print "Unable to determine if the port is filtered"
在本地文件系統(tǒng)創(chuàng)建腳本之后,需要更新文件許可來允許腳本執(zhí)行。chmod可以用于更新這些許可,腳本之后可以通過直接調(diào)用并傳入預(yù)期參數(shù)來執(zhí)行:
root@KaliLinux:~# chmod 777 ACK_FW_detect.py
root@KaliLinux:~# ./ACK_FW_detect.py
Usage - ./ACK_FW_detect.py [Target-IP] [Target Port]
Example - ./ACK_FW_detect.py 10.0.0.5 443
Example will determine if filtering exists on port 443 of host 10.0.0.5
root@KaliLinux:~# ./ACK_FW_detect.py 172.16.36.135 80 Port is unfiltered and open
root@KaliLinux:~# ./ACK_FW_detect.py 172.16.36.134 22 Host is either unstatefully filtered or is down
工作原理
SYN 和 ACK TCP 標(biāo)志在有狀態(tài)的網(wǎng)絡(luò)通信中起到關(guān)鍵作用。SYN 請求允許建立新的 TCP 會話,而 ACK 響應(yīng)用于在關(guān)閉之前維持會話。端口響應(yīng)這些類型的封包之一,但是不響應(yīng)另一種,就可能存在過濾,它基于會話狀態(tài)來限制流量。通過識別這種情況,我們就能夠推斷出端口上存在狀態(tài)過濾。
4.15 Nmap 防火墻識別
Nmap 擁有簡化的防火墻過濾識別功能,基于 ACK 探測響應(yīng)來識別端口上的過濾。這個功能可以用于測試單一端口或者多個端口序列來判斷過濾狀態(tài)。
準(zhǔn)備
為了使用 Nmap 來執(zhí)行防火墻識別,你需要運(yùn)行網(wǎng)絡(luò)服務(wù)的遠(yuǎn)程系統(tǒng)。此外,你需要實(shí)現(xiàn)一些過濾機(jī)制。這可以使用獨(dú)立防火墻設(shè)備,或者基于主機(jī)的過濾,例如 Windows 防火墻來完成。通過操作防火墻設(shè)備的過濾設(shè)置,你應(yīng)該能夠修改被注入封包的響應(yīng)。
操作步驟
為了使用 Nmap 執(zhí)行防火墻 ACK 掃描,Nmap 應(yīng)該以指定的 IP 地址,目標(biāo)端口和-sA選項(xiàng)調(diào)用。
root@KaliLinux:~# nmap -sA 172.16.36.135 -p 22
Starting Nmap 6.25 ( http://nmap.org ) at 2014-01-24 11:21 EST
Nmap scan report for 172.16.36.135
Host is up (0.00032s latency).
PORT STATE SERVICE
22/tcp unfiltered ssh
MAC Address: 00:0C:29:3D:84:32 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 0.05 seconds
root@KaliLinux:~# nmap -sA 83.166.169.228 -p 22
Starting Nmap 6.25 ( http://nmap.org ) at 2014-01-24 11:25 EST
Nmap scan report for packtpub.com (83.166.169.228)
Host is up (0.14s latency).
PORT STATE SERVICE
22/tcp filtered ssh
Nmap done: 1 IP address (1 host up) scanned in 2.23 seconds
通過在本地網(wǎng)絡(luò)中的 Metasploitable2 系統(tǒng)上執(zhí)行掃描,流量并不經(jīng)過防火墻,響應(yīng)表明 TCP 22 端口是未過濾的。但是,如果我對packtpub. com的遠(yuǎn)程 IP 地址執(zhí)行相同掃描,端口 22 是過濾器的。通過執(zhí)行相同掃描,而不指定端口,端口過濾評估可以在 Nmap 的 1000 個常用端口上完成。
root@KaliLinux:~# nmap -sA 172.16.36.135
Starting Nmap 6.25 ( http://nmap.org ) at 2014-01-24 11:21 EST
Nmap scan report for 172.16.36.135
Host is up (0.00041s latency). All 1000 scanned ports on 172.16.36.135 are unfiltered
MAC Address: 00:0C:29:3D:84:32 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds
對本地網(wǎng)絡(luò)上的 Metasploit2 系統(tǒng)執(zhí)行掃描時,由于它沒有被任何防火墻保護(hù),結(jié)果表明所有端口都是未過濾的。如果我們在packtpub.com域內(nèi)執(zhí)行相同掃描,所有端口都識別為存在過濾,除了 TCP 端口 80,這是 Web 應(yīng)用部署的地方。要注意在掃描端口范圍的時候,輸出只包含未過濾的端口。
root@KaliLinux:~# nmap -sA 83.166.169.228
Starting Nmap 6.25 ( http://nmap.org ) at 2014-01-24 11:25 EST
Nmap scan report for packtpub.com (83.166.169.228)
Host is up (0.15s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
80/tcp unfiltered http
Nmap done: 1 IP address (1 host up) scanned in 13.02 seconds
為了在所有可能的 TCP 端口上執(zhí)行掃描,需要奧妙所有可能的端口地址。定義了來源和目標(biāo)端口地址的 TCP 頭部部分是 16 位長,每一位可以為值 1 或者 0。所以一共有2 **16或 65536 個 TCP 端口地址。為了掃描所有可能的地址空間,必須提供 1 到 65535 的 范圍。
root@KaliLinux:~# nmap -sA 172.16.36.135 -p 1-65535
Starting Nmap 6.25 ( http://nmap.org ) at 2014-01-24 11:21 EST
Nmap scan report for 172.16.36.135
Host is up (0.00041s latency).
All 65535 scanned ports on 172.16.36.135 are unfiltered
MAC Address: 00:0C:29:3D:84:32 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 1.77 seconds
工作原理
除了 Nmap 提供的許多功能,它也可以用于識別防火墻過濾。這意味著 Nmap 通過使用之前在 Scapy 秘籍中討論的相同技巧,來執(zhí)行這種防火墻識別。SYN 和 來路不明的 ACK 的組合會發(fā)送給目標(biāo)端口,響應(yīng)用于分析來判斷過濾狀態(tài)。
4.18 Metasploit 防火墻識別
Metasploit 擁有一個掃描輔助模塊,可以用于指定多線程網(wǎng)絡(luò)端口分析,基于 SYN/ACK 探測響應(yīng)分析,來判斷端口是否被過濾。
準(zhǔn)備
為了使用 Metasploit 來執(zhí)行防火墻識別,你需要運(yùn)行網(wǎng)絡(luò)服務(wù)的遠(yuǎn)程系統(tǒng)。此外,你需要實(shí)現(xiàn)一些過濾機(jī)制。這可以使用獨(dú)立防火墻設(shè)備,或者基于主機(jī)的過濾,例如 Windows 防火墻來完成。通過操作防火墻設(shè)備的過濾設(shè)置,你應(yīng)該能夠修改被注入封包的響應(yīng)。
操作步驟
為了使用 Metasploit ACK 掃描模塊來執(zhí)行防火墻和過濾識別,你首先必須從 Kali 的終端中啟動 MSF 控制臺,之后使用use命令選項(xiàng)所需的輔助模塊。
root@KaliLinux:~# msfconsole
# cowsay++
____________
< metasploit >
-----------
\ ,__,
\ (oo)____
(__) )\
||--|| *
Using notepad to track pentests? Have Metasploit Pro report on hosts, services, sessions and evidence -- type 'go_pro' to launch it now.
=[ metasploit v4.6.0-dev [core:4.6 api:1.0]
+ -- --=[ 1053 exploits - 590 auxiliary - 174 post
+ -- --=[ 275 payloads - 28 encoders - 8 nops
msf > use auxiliary/scanner/portscan/ack
msf auxiliary(ack) > show options
Module options (auxiliary/scanner/portscan/ack):
Name Current Setting Required Description
---- --------------- -------- ----------
BATCHSIZE 256 yes The number of hosts to scan per set
INTERFACE no The name of the interface
PORTS 1-10000 yes Ports to scan (e.g. 22- 25,80,110-900)
RHOSTS yes The target address range or CIDR identifier
SNAPLEN 65535 yes The number of bytes to capture
THREADS 1 yes The number of concurrent threads
TIMEOUT 500 yes The reply read timeout in milliseconds
一旦選擇了模塊,可以使用show options命令來確認(rèn)或更改掃描配置。這個命令會展示四個列的表格,包括name、current settings、required和description。name列標(biāo)出了每個可配置變量的名稱。current settings列列出了任何給定變量的現(xiàn)有配置。required列標(biāo)出對于任何給定變量,值是否是必須的。description列描述了每個變量的功能。任何給定變量的值可以使用set命令,并且將新的值作為參數(shù)來修改。
msf auxiliary(ack) > set PORTS 1-100
PORTS => 1-100
msf auxiliary(ack) > set RHOSTS 172.16.36.135
RHOSTS => 172.16.36.135
msf auxiliary(ack) > set THREADS 25
THREADS => 25
msf auxiliary(ack) > show options
Module options (auxiliary/scanner/portscan/ack):
Name Current Setting Required Description
---- --------------- -------- ----------
BATCHSIZE 256 yes The number of hosts to scan per set
INTERFACE no The name of the interface
PORTS 1-100 yes Ports to scan (e.g. 22- 25,80,110-900)
RHOSTS 172.16.36.135 yes The target address range or CIDR identifier
SNAPLEN 65535 yes The number of bytes to capture
THREADS 25 yes The number of concurrent threads
TIMEOUT 500 yes The reply read timeout in milliseconds
在上面的例子中,RHOSTS值修改為我們打算掃描的遠(yuǎn)程系統(tǒng)的 IP 地址。此外,線程數(shù)量修改為 20。THREADS的值定義了在后臺執(zhí)行的當(dāng)前任務(wù)數(shù)量。確定線程數(shù)量涉及到尋找一個平衡,既能提升任務(wù)速度,又不會過度消耗系統(tǒng)資源。對于多數(shù)系統(tǒng),20 個線程可以足夠快,并且相當(dāng)合理。修改了必要的變量之后,可以再次使用show options命令來驗(yàn)證。一旦所需配置驗(yàn)證完畢,就可以執(zhí)行掃描了。
msf auxiliary(ack) > run
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
這個例子中,唯一提供的輸出就是有關(guān)掃描的源信息,它顯示了被掃描系統(tǒng)的數(shù)量,以及模塊執(zhí)行完畢。輸出的缺乏是因?yàn)椋?SYN 以及 ACK 注入相關(guān)的響應(yīng)從一個端口直接到達(dá)另一個端口,因?yàn)?Metasploitable2 系統(tǒng)沒有任何防火墻。作為替代,如果我們在packtpub.com域上執(zhí)行相同掃描,通過將RHOSTS值修改為和它相關(guān)的 IP 地址,我們會收到不用的輸出。因?yàn)檫@個主機(jī)放在防火墻背后,和未過濾端口相關(guān)的響應(yīng)中的變化如下:
msf auxiliary(ack) > set RHOSTS 83.166.169.228
RHOSTS => 83.166.169.228
msf auxiliary(ack) > show options
Module options (auxiliary/scanner/portscan/ack):
Name Current Setting Required Description
---- --------------- -------- ----------
BATCHSIZE 256 yes The number of hosts to scan per set
INTERFACE no The name of the interface
PORTS 1-100 yes Ports to scan (e.g. 22- 25,80,110-900)
RHOSTS 83.166.169.228 yes The target address range or CIDR identifier
SNAPLEN 65535 yes The number of bytes to capture
THREADS 25 yes The number of concurrent threads
TIMEOUT 500 yes The reply read timeout in milliseconds
msf auxiliary(ack) > run
[*] TCP UNFILTERED 83.166.169.228:80
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
工作原理
Metasploit 擁有一個輔助模塊,可以以多種技巧執(zhí)行防火墻識別,這些技巧之前討論過。但是,Metasploit 也提供了一些功能來分析防火墻上下文,可以用于其它信息的收集甚至是利用。