Nmap-服務探測

Nmap的服務探測


1. 服務探測流程


服務探測流程圖

1. Nmap先做端口掃描,然後把狀態爲open或者是open|filtered的TCP或UDP端口傳遞給服務識別模塊,最後這些端口會並行的做服務探測。
2. Nmap檢查端口是否是需要排除的端口(見下文的Exclude Directive),如果是需要排除的端口那麼Nmap不會對這個端口做服務探測。這裏主要是避免對一些打印機的服務端口發包。
3. 如果端口是TCP,Nmap會先和端口建立一個連接,如果連接成功並且這個端口的狀態原來是open|filtered的,那麼Nmap把這個端口的狀態改成open。這樣做對那些爲了隱祕掃描(例如FIN scan)而識別端口爲open|filtered非常有用,這樣能進一步確認端口的狀態。
4. 一旦上面的連接建立,Nmap嘗試等待6s(以前是5s)。一些常見的服務,包括大部分的FTP、SSH、SMTP、Telnet、POP3、IMAP服務,爲了標示自己會對建立的連接發送一些Welcome banner信息,這個過程稱爲NULL ProbeNULL Probe僅僅是和目標端口建立連接,沒有發送任何的數據(也就是隻經過了TCP的三次握手),在等待的時間內如果收到了數據,Nmap會將收到的banner信息和NULL Probe的將近3000個服務簽名特徵進行匹配(下文中的match Directive)。假如服務完全識別了(個人理解就是服務和版本信息都識別出來了),那麼這個端口的服務識別就結束了。有時候Nmap只匹配到了服務類型,沒有匹配到版本信息(下文softmatch Directive),那麼Nmap會繼續進行掃描,因爲已經識別出來了服務那麼Nmap會有針對的發送Probe。
5. UDP Probe或者前面的NULL Probe匹配失敗再或者是NULL Probe有soft match,那麼就會接着順序進行nmap-service-probes文件中其他的Probe。
 每一個服務都註冊到了一個常見的端口中(通過nmap-services文件),每一個service probe都包含了一個端口的列表,表示在這些端口上面最有可能開放這個服務。例如 GetRequest是一個識別web servers的Probe,包含的端口爲80-85、8000-8010(不限於這些端口),那麼Nmap在掃描的時候會順序對這些開放的端口進行GetRequest probe探測。
6. 每一個probe包含了一個probe string,在服務探測的時候發送給目標端口,目標返回的數據會和這個對應的probe的一系列特徵字符串(signature,下文中的match Directive)進行匹配。如果匹配成功則服務識別結束,如果是一個softmatch那麼Nmap有選擇的進行下一步probe,要是都匹配失敗則看是否有fallback Directive,如果有則執行fallback Directive,更具體的參考fallback Directive和Cheats and Fallback部分。
 在服務探測期間如果收到了來自UDP端口的數據,並且端口的UDP狀態爲open|filtered那麼Nmap把這個端口的UDP狀態改成open。在UDP掃描的時候如果因爲有防火牆的干擾導致所有的端口狀態爲open|filtered,那麼結合服務探測對端口的狀態做進一步的探測,這是非常有用的。
7. 在大部分的情況下,NULL probe和接下來的一個probable port probe(probable port probe:我理解就是ports Directive指令中包含這個端口)就能夠識別出來服務。NULL probeprobable port probe公用同一個連接,所以在大部分情況下只要簡單的建立一個連接就可以識別出來服務。
 如果NULL probeprobable probe沒有識別出來服務,Nmap會繼續按序嘗試其他的probe。那麼對於TCP來說不得不重新建立一個連接(對於UDP來說就只要一個包就可以了),因爲爲了避免不同的probe之間相互影響,有可能前面發送的probe在超時以後還會收到目標端口的迴應數據,沒有重新建立連接那麼Nmap就會分不清楚迴應的數據對應的是哪個probe。這個重新建立連接可能會要花費點時間了,如果再算上Nmap必須設置6s的超時來等待數據的返回,那麼這就更加糟糕了。爲了應對這種糟糕的情況,Nmap利用了幾種技術來加快掃描的速度:

  • Nmap儘可能使每一個probe匹配多個服務。例如GenericLines probe發送兩個換行符("\r\n\r\n")給目標端口,這樣就可以匹配許多的服務,包括FTP、ident、POP3、UUCP、Postgres和whois。GetRequest probe匹配了更多的服務,類似的還有HELP probe("help\r\n")和RPC、MS SMB probe。
  • 如果一個服務是soft match,那麼Nmap只會去嘗試可能匹配服務的probe(也就是說Nmap會有目的和針對性的進行probe)。
  • 所有的probe都是不等價的!有一些匹配更多的服務,基於此Nmap用rarity度量值(rarity Directive)來避免嘗試那些可能匹配失敗的probe。我們可以用--version-intensity, --version-all, and --version-light選項來選擇rarity值。

8. 有一個probe會探測目標端口是否正在運行於SSL之上,如果探測成功Nmap會通過SSL連接重新探測這個服務,識別出運行於SSL加密後的真正服務。例如,Nmap會對443端口進行SSL probe,如果探測成功則嘗試GetRequest probe,因爲一般有一個web服務運行於SSL加密之後。
9. 另外一個通用的probe識別會去基於RPC的一些服務,一旦探測成功Nmap RPC grinder就會初始化,開始暴力(翻譯有點不準)探測RPC程序的版本、名稱。
10. 至少有一個probe會導致目標迴應數據,如果Nmap沒有成功識別出來服務,那麼目標迴應的數據會作爲特徵值(fingerprint)輸出,如果你知道目標運行的服務那麼你可以把fingerprint提交給Nmap,集成到nmap-probe-services中。

2. Cheats and Fallbacks

 儘管Nmap會等待幾秒時間等待目標服務返回數據,有時候一些應用對NULL Probe的迴應會比較慢。可能是多重原因導致的這種慢,比如一個慢的DNS反向查詢。基於這個原因,Nmap有時候會在後續的Probe中接受到NULL Probe的返回數據。
 例如,我們掃描端口25(SMTP),只要我們一建立連接,SMTP服務會要去一大堆的DNS黑名單中查詢我們是否是垃圾郵件發送者,如果是就拒絕服務。這個過程可能比較耗時間,可能會超過Nmap的NULL Probe等待時間,如果超時那麼Nmap會接着順序執行後面的其他probe,對於25端口接下來是HELP Probe。當SMTP做完anti-spam的檢查發現我們不是垃圾郵件者,它會回送greeting banner如下。在接受到NULL Probe返回的banner信息時Nmap因爲超時已經到了HELP Probe這個步驟了,將收到的banner和HELP Probe的特徵字符串進行匹配,匹配失敗。

220 hcsw.org ESMTP Sendmail 8.12.3/8.12.3/Debian-7.1; Tue, [cut]
214-2.0.0 This is sendmail version 8.12.3
214-2.0.0 Topics:
214-2.0.0 HELO EHLO MAIL RCPT DATA
214-2.0.0 RSET NOOP QUIT HELP VRFY
214-2.0.0 EXPN VERB ETRN DSN AUTH
214-2.0.0 STARTTLS
214-2.0.0 For more info use “HELP ”.
214-2.0.0 To report bugs in the implementation send email to
214-2.0.0 [email protected].
214-2.0.0 For local information send email to Postmaster at your site.
214 2.0.0 End of HELP info

 因爲這是一個比較普遍的問題,Nmap會有一個"欺騙(cheats)"動作,如果當前的probe匹配失敗則會嘗試去匹配NULL Probe。在上面的SMTP例子中,我們會在NULL Probe中匹配成功,識別服務爲SMTP,程序是Sendmail,版本是8.12.3/8.12.3/Debian-7.1,並且主機名是hcsw.org
 上面提到的NULL Probe的cheat過程其實是Nmap的一個通用的特徵:fallbacks。fallback directive指令在下文中會詳細描述了,基本上每一個可能會在當前的匹配過程中遇到其他的probe的迴應數據的probe,都會定義一些fallback directive。
 例如,有一些Apache服務器的設置,Apache不會迴應GetRequest("GET / HTTP/1.0\r\n\r\n")probe的請求,但是Nmap還是能夠正確的識別出來這個服務,因爲這些服務會迴應HTTPOptions probe,這個HTTPOptions probe有一個fallback directive指向GetRequest。在GetRequest probe中有足夠的特徵值(signature)可以識別出來服務(這裏其實應該是假設HTTPOptions沒有成功識別)。

3. Probe 的選擇和優先級

 Nmap用rarity(優先級)來決定選用哪些probe進行服務探測,rarity值高表示這個probe是不常用的而且probe返回的數據不太有用。Nmap的使用者可以通過如下所示的服務掃描強度(version-intensity)參數來決定使用哪個probe進行服務探測。Nmap選擇probe的完整算法如下:

  1. 對TCP來說,NULL Probe總是第一個使用的。
  2. 所有ports Directivesslports Directive包含了該端口的probe都將按照在nmap-service-probes出現的順序被使用。例如對於6000端口來說,probe的選擇順序爲:NULL probeHTTPOptions probeX11Probe probeibm-db2 probe
  3. 其他rarity值小於等於本次指定的version-intensity值的probe被調用,這些probe也是按照在nmap-service-probes出現的順序被使用。
  4. 只要有任何一個probe匹配到了服務,那麼本次服務探測結束。

除了NULL probe以外的probe都會有一個rarity,在Nmap進行服務識別的時候我們可以靈活的控制使用哪些probe,在每次掃描的時候選用一個合適的version-intensity值即可。version-intensity值越高,使用的probe越多,所以一個全面的掃描就需要選擇一個高強度的version-intensity值,當然version-intensity值越高需要的掃描時間越長。Nmap默認的version-intensity值爲7,Nmap提供如下的選項:

–version-intensity <intensity level between 0 and 9>
設置掃描的服務探測強度,如果爲0則只有NULL probe和端口在ports Directive列表中的probe會被調用


–version-light
等價於–version-intensity 2。


–version-all
等價於–version-intensity 9,所有的probe都被使用。

1. Exclude Directive:排除指令是指在做服務識別時需要排除的端口,這個命令只能使用一次,一般是放在了文件的頭部(也就是任何探測命令之前)。在nmap-service-probes文件中默認包含了tcp端口的9100到9107之間的端口(Exclude T:9100-9107),這是因爲這些端口一般都是用於打印機的,這些監聽的端口會打印數據只要你給這個端口發送了任何的數據。你可以使用—allports選項,這樣服務探測會去探測所有的端口。
2. Probe Directive:探測指令告訴Nmap發送何種字符串去識別各種服務,也就是定義了一個探測包。
Probe的語法爲:Probe protocol probename probestring
示例:Probe TCP X11Probe q|\x6C\0\x0B\0\0\0\0\0\0\0\0\0|
protocol:
 這個只能是TCP或者UDP。Nmap只會對這兩種協議的服務做probe
probename:
 這是給本次的probe取的名稱,個人猜測在Nmap中會有很多的地方用這個probename來代表這個服務probe。在後面的fallback Directive中我們會遇到使用這個probename,還有在Nmap指定--version-trace選項後會打印出來對這個端口做了哪些服務probe,在這裏就會使用這個probe name,如:Service scan sending probe Help to 192.168.1.1:3389 (tcp)
probestring:
  Nmap爲了服務探測發送的字符串。Probestring必須以"q"字母開頭,然後以分隔符"|"爲字符串的開頭和結尾。在分隔符之間是真正發送的字符,發送的字符格式跟C or Perl字符格式類似,允許這些轉義字符:\\ \0, \a, \b, \f, \n, \r, \t, \v, and \xHH(H是十六進制數字)。有一個特殊的probestring,叫做TCP NULL probe,分隔符之間的字符串爲空(Probe TCP NULL q||),這個特殊的probe的作用見下面的章節。如果你想在probestring中包含分隔符那麼你可能需要選擇除|以外的字符。
3. match Directive:匹配指令告訴Nmap如何從目標機返回的字符串中識別出來服務。
match的語法爲:match service pattern [versioninfo]
示例:match networkaudio m|^\0\x19\x02\0\x02\0\x07\0Protocol version mismatch\0| p/Network Audio System/
service:
 這是和pattern相匹配的服務名稱.例如是ssh,smtp,http.可以在服務名前增加ssl標誌,表示這個服務是通過SSL隧道加密的.
pattern:
 這是用於識別返回的字符串是否匹配對應的服務。pattern的格式跟Perl類似,語法是m/[regex]/[opts],"m"表示字符串的開始,接着的/是分隔符,這個分隔符可以是任何其他可打印的字符只要和接下來的分隔符相匹配即可。[regex]部分是一個Perl風格的表達式,目前僅支持i、s這兩個選項,分別表示大小寫不敏感和’.’元字符包括換行符。這兩個選項和我們一般的正則表達式中的意義一致。[regex]還支持分組。
versioninfo:
 versioninfo部分包含了幾個可選的子選項。每一個選項都由一個特定的標示符開始(例如h代表”hostname”),接下來是一個分隔符(分隔符雖然可以是不同的字符但是強烈建議用斜線/),再接着就是選項的值,下面是所有可能的選項格式:




 上面所列的選項都可能爲空。在這些選項中可能經常會遇到$1、$2這樣的數字,這些其實就是我們正則表達式中的分組引用(引用pattern中的分組)。
4. softmatch Directive
語法:softmatch <service> <pattern>
示例:softmatch ftp m/^220 [-.\w ]+ftp.*\r\n$/i
 softmatch指令和上文的match(上文的match其實可以理解爲hard match)指令差不多,主要的一個不同就是softmatch以後會要繼續執行其他的probe,但是後面執行的probe是有選擇性的,因爲softmatch已經識別出來了服務,之所以在識別出來服務以後還要繼續執行是爲了進一步識別版本號。比如我們識別出來目標端口開放了http服務,但是沒有能識別出來app是Apache還是Nginx或者是IIS。
 在nmap官網中提到softmatch指令不會有<versioninfo>部分,但是我在最新的nmap 6.47的nmap-service-probes文件中卻看到softmatch也會有versioninfo部分,這個是暫時未搞清楚的。
5. Ports and sslports Directive
語法:ports <端口列表>
示例:ports 111,4045,32750-32810,38978
Ports(sslports)指令告訴Nmap該probe識別的服務一般都在哪些端口上面監聽(運行),每一個probe只能有一個ports(sslports)指令。
6. Totalwaitms Directive
語法:totalwaitms milliseconds
示例:totalwaitms 6000
 Totalwaitms指令表示本次probe的超時等待時間。這個指令一般不太常用,probe在發送了數據會在指定的時間等待目標數據返回。在Nmap中這個值默認爲6000(雖然book上面說是5000,但是看了一下最新的nmap-service-probes中是6000)。
7. Rarity Directive
語法:rarity <0-9>
示例:rarity 7
 rarity指令表示改probe被調用的優先級,值越高表示被調用的優先級越低,也就代表該probe能夠正確識別服務的概率越低(也可以理解爲該probe識別的服務不常見)。
8. fallback Directive:回退指令,如果當前定義的特徵值沒有匹配到(match Directive failed),並且指定了fallback指令那麼回退到指定的probe再進行匹配。
fallback語法:fallback <comma separated list of probes>
示例:fallback GetRequest,GenericLines
 fallback是可選的指令。對TCP probe如果沒有定義fallback指令,Nmap會首先和當前定義的Probe進行匹配,並且會隱式的回退(fallback)到NULL Probe進行匹配(當然是當前的probe匹配失敗)。如果定義了fallback指令,那麼在當前的probe匹配失敗後會回退到fallback定義的probe去進行匹配,如果繼續匹配失敗則回退到NULL probe進行匹配。
 UDP probe流程相同,除了隱式的回退到NULL probe。
 至於爲什麼要有fallback指令可以參考上文的"Nmap的服務探測流程"。

4. 服務探測抓包分析

 實踐是檢驗真理的唯一標準,那麼下面就用一些示例來近一步瞭解Nmap的服務探測過程。我們可以用—version-trace或者-d(debugging)來查看Nmap的服務探測整個過程,還可以結合網絡抓包來查看網絡發包情況。
 下面是Nmap中提到的一個示例,掃描參數爲:nmap -sSV -T4 -F -d --version-trace insecure.org

Service scan sending probe NULL to 173.255.243.189:22 (tcp)
NSOCK INFO [3.6630s] nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 50 [173.255.243.189:22] (21 bytes): SSH-2.0-OpenSSH_5.3..
Service scan match (Probe NULL matched with NULL line 2951): 173.255.243.189:22 is ssh. Version: |OpenSSH|5.3|protocol 2.0|

22端口的Nmap輸出
22端口的wireshark輸出

結合上面兩個輸出來看:

  • 22號端口運行的是SSH服務。
  • Nmap在NULL probe中就完整識別出來了22端口的服務。
  • NULL probe其實就是TCP的三次握手過程,連接建立後沒有發送任何數據給目標端口。

Service scan sending probe NULL to 173.255.243.189:80 (tcp)
NSOCK INFO [0.6230s] nsock_read(): Read request from IOD #1 [173.255.243.189:80] (timeout: 6000ms) EID 18
NSOCK INFO [6.6300s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 18 [173.255.243.189:80]
Service scan sending probe GetRequest to 173.255.243.189:80 (tcp)
NSOCK INFO [6.7820s] nsock_trace_handler_callback(): Callback: READ SUCCESS for EID 34 [173.255.243.189:80] (1448 bytes)
Service scan match (Probe GetRequest matched with GetRequest line 5555): 173.255.243.189:80 is http. Version: |Apache httpd|2.2.15|(CentOS)|

80端口的Nmap輸出
22端口的wireshark輸出
  • 80端口運行的服務是http。
  • Nmap在NULL probe中沒有識別出來80端口的服務,在NULL probe中Nmap會等待6000ms的時間。在6000ms超時以後繼續執行了GetRequest probe,並且在GetRequest probe中完整識別出來了80端口的服務。
  • Nmap在NULL probe和接下來的第一個probe中會共用同一個tcp連接,除此之外的probe都需要單獨重新建立連接(在這個示例中沒有體現出來,在下面的示例中有體現)。

    下面這個是我模擬了一個14000端口的開放,上面沒有運行任何的服務,用Nmap對這個端口進行了掃描,掃描參數爲:nmap -Pn -sT -sV --version-intensity 6 -p 14000 10.16.60.106 -e eth1 -n --open --version-trace

Service scan sending probe NULL to 10.16.60.106:14000 (tcp)
NSOCK INFO [6.1410s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 18 [10.16.60.106:14000]
Service scan sending probe GenericLines to 10.16.60.106:14000 (tcp)
NSOCK INFO [11.1480s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 34 [10.16.60.106:14000]
Service scan sending probe GetRequest to 10.16.60.106:14000 (tcp)
NSOCK INFO [16.1610s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 58 [10.16.60.106:14000]
Service scan sending probe HTTPOptions to 10.16.60.106:14000 (tcp)
NSOCK INFO [21.1740s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 82 [10.16.60.106:14000]
Service scan sending probe RTSPRequest to 10.16.60.106:14000 (tcp)
NSOCK INFO [26.1910s] nsock_trace_handler_callback(): Callback: READ TIMEOUT for EID 106 [10.16.60.106:14000]

14000端口的Nmap輸出

14000端口的wireshark輸出

GenericLines probe發送的數據

GetRequest probe發送的數據

HTTPOptions probe發送的數據

RTSPRequest probe發送的數據
  • Nmap沒有能識別出來14000開放的服務。
  • NULL probeGenericLines probe是共用一個tcp連接,但是接下來的GetRequest probe是重新建立的tcp連接。
  • Nmap對14000端口共進行了5次服務探測,在nmap-service-probes文件中沒有哪個probe的ports Directive包含了14000端口,也就是說14000沒有probable probe。但是因爲在參數中指定了--version-intensity 6,所以Nmap把rarity < 6的probe都執行了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章