掃描對外公開的服務器信息,是 nmap 的主要用途之一。爲了識別服務器上運行的是哪一種服務,nmap 把主流服務的特徵信息存儲在 nmap-services-probes 和 nmap-os-db 這兩個文件中。其中前者包含應用程序的特徵信息,後者放置操做系統的特徵信息。不一樣操做系統上,這兩個文件的位置不同,能夠經過 locate
或其餘類似的全盤搜索工具找出它們具體的位置。html
接下來讓咱們解讀下這兩個文件,看看 nmap 是如何利用這些信息來識別服務的。python
當咱們指定 -sV
選項運行 nmap 時,它會根據 nmap-services-probes 文件裏面存儲的是服務類型特徵數據去判斷具體掃描到的是哪一種服務。linux
nmap-services-probes 看上去比較亂。事實上,若是這部分數據能夠組織成 xml 或 yaml 這種樹型結構的格式,看上去會明顯清晰得多。nginx
貼個片斷看下:正則表達式
Probe TCP GetRequest q|GET / HTTP/1.0\r\n\r\n| rarity 1 ports 1,70,79,80-85,88,113,139,143,280,497,505,514,515,540,554,591,620,631,783,888,898,900,901,1026,1080,1042,1214,1220,1234,1314,1344,1503,1610,1611,1830,1900,2001,2002,2030,2064,2160,2306,2396,2525,2715,2869,3000,3002,3052,3128,3280,3372,3531,3689,3872,4000,4444,4567,4660,4711,5000,5427,5060,5222,5269,5280,5432,5800-5803,5900,5985,6103,6346,6544,6600,6699,6969,7002,7007,7070,7100,7402,7776,8000-8010,8080-8085,8088,8118,8181,8880-8888,9000,9001,9030,9050,9080,9090,9999,10000,10001,10005,11371,13013,13666,13722,14534,15000,17988,18264,31337,40193,50000,55555 sslports 443,993,995,1311,1443,3443,4443,5061,7443,8443,9443,10443,14443,44443,60443 ... match http m|^HTTP/1\.[01] \d\d\d.*?\r\nServer: nginx\r\n|s p/nginx/ cpe:/a:igor_sysoev:nginx/ match http m|^HTTP/1\.[01] \d\d\d.*\r\nServer: nginx/([\d.]+)\r\n|s p/nginx/ v/$1/ cpe:/a:igor_sysoev:nginx:$1/
nmap-services-probes 沒有直接列出各類服務的特徵,而是描述了服務識別掃描過程當中的操做步驟。其中 Probe
開頭表示新起一個探測項。後面跟着的 TCP GetRequest
表示該探測項的種類和名字。q|GET / HTTP/1.0\r\n\r\n|
表示探測時採起的動做,這裏就是發送一個最小的 GET 請求。redis
下一行的 rarity 表示該探測的罕見性。nmap 默認只會執行 rarity 7 如下的探測,不過能夠經過 --version-intensity N
選項更改。服務器
再往下,是須要執行該探測的端口列表。在發起識別服務的掃描以前,nmap 已經掃描出當前可用的端口列表了。對於列表中的端口,若是它在某個探測的端口列表裏,nmap 就會對該端口執行對應的探測。不用擔憂每一個端口都執行許多探測會明顯減慢掃描速度 —— nmap 會並行掃描多個端口。tcp
sslports 相似於 ports,不一樣之處在於生效的時間。當 nmap 完成 tls 握手後,會根據 sslports 登記的配置去運行對應的探測。工具
接下來是一連串的 match 語句。顧名思義,它們都是響應的匹配規則。其中 m 開頭的是正則表達式,p 開頭的是產品名字,v 開頭的是版本號,cpe 開頭的是 cpe 編號, i 開頭表示附加的信息。這裏列出的匹配規則表示,若是 GET 請求對應的響應匹配到 ^HTTP/1\.[01] \d\d\d.*?\r\nServer: nginx\r\n
,說明對應的服務是 Nginx。單個產品可能會有多個與之相關的規則,好比 nmap 會有如下方法去匹配 Nginx:測試
<center>nginx</center>
<head><title>400 Bad Request</title></head>\r\n<h1>400 Bad Request</h1>
HTTP/1.1 400 Bad Request\r\n.*<title>400 The plain HTTP request was sent to HTTPS port</title>
match 語句最多隻會匹配到一個服務。若是想匹配多個服務,好比 Nginx 代理的 PHP 應用,能夠結合 softmmatch 使用。添加下面一行:
softmatch http m|^HTTP/1\.[01] .*\r\nX-Powered-By: PHP/(\d[\w._-]+)|s i/PHP $1/
最後輸出結果裏會多一個括號:8080/tcp open http nginx (PHP 5.6.25)
。
除了 HTTP 請求,nmap 也會用其餘方式探測目標服務,好比這個爲 Redis 量身定製的請求:Probe TCP redis-server q|\*1\r\n\$4\r\ninfo\r\n|
。甚至連 minecraft 都有:Probe TCP minecraft-ping q|\xFE\x01|
。
nmap-service-probes 開頭的 Probe TCP NULL q||
值得介紹。這個 Probe 是爲了檢測出某些會主動給連上來的客戶端發送數據的服務設置的。跟其餘 Probe 不一樣,它不發送請求,只是乾等 6 秒。當你給 nmap 抓包時,端口探測和服務識別間會相差 6 秒,就是這個探測致使的。
附贈一個列出全部可探測的服務的 Python 腳本:
import re # 以實際位置替換下面的路徑 nmap_service_probes_file = "/usr/local/share/nmap/nmap-service-probes" pat = re.compile(r"^match .+ p/([^/]+)/ .+$") products = set() with open(nmap_service_probes_file) as f: for line in f: m = pat.search(line) if m is not None and not m.group(1).startswith('$'): # 會存在 product 名中間含有 $xx 變量的狀況,這裏就忽略吧 products.add(m.group(1)) for p in sorted(list(products)): print(p)
跟 -sV
選項相似,有一個名爲 -O
的選項能夠開啓操做系統探測的掃描功能。依本人的經驗,nmap 的 操做系統探測的準確度僅到操做系統類型這一級,對於具體的版本,其掃描結果可能會不許。
掃描過程當中會用到 nmap-os-db 這個文件裏面的特徵信息識別遇到的 OS。若是說 nmap-service-probes 相對還好閱讀,那 nmap-os-db 無疑即是天書通常了。還好 nmap 的文檔裏面對此有充分的解釋,參見:
操做系統探測利用的是 IP/TCP 層面上的特徵。在 nmap-os-db 裏面,每一個特徵以 Fingerprint 開頭,接着是該特徵對應的操做系統信息,而後是具體的特徵值。
舉個例子,像下面這樣的特徵數據:
Fingerprint Linux 3.10 Class Linux | Linux | 3.X | general purpose CPE cpe:/o:linux:linux_kernel:3.10 auto SEQ(SP=FB-105%GCD=1-6%ISR=109-113%TI=Z%CI=I%II=I%TS=A) OPS(O1=M548ST11NW7%O2=M548ST11NW7%O3=M548NNT11NW7%O4=M548ST11NW7%O5=M548ST11NW7%O6=M548ST11) WIN(W1=3890%W2=3890%W3=3890%W4=3890%W5=3890%W6=3890) ECN(R=Y%DF=Y%T=3B-45%TG=40%W=3908%O=M548NNSNW7%CC=Y%Q=) T1(R=Y%DF=Y%T=3B-45%TG=40%S=O%A=S+%F=AS%RD=0%Q=) T2(R=N) T3(R=N) T4(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) T5(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) T6(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) T7(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) U1(DF=N%T=3B-45%TG=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G) IE(DFI=N%T=3B-45%TG=40%CD=S)
看上去仍是人話的前三行描述了該特徵對應的 OS。須要解釋的是鬼畫符通常的後面幾行。
每一行都是一項測試的結果,其中 XXX()
中的 XXX 是測試的名字。括號內以 %
分隔的各項是測試中的各類指標。每項指標的值都是 K-V 形式,K 是指標的名字,而 V 具體怎麼解釋,則各個指標各個不一樣。具體表明什麼煩請查閱 https://nmap.org/book/osdetec... 。
全部的測試分紅五組,詳見 https://nmap.org/book/osdetec... 的說明。第一組測試包含 SEQ、OPS、WIN、T1。這項測試會發送六個 TCP 包,而後檢查響應的各類細節。第二組測試是 IE,會發送兩個不一樣的 ICMP echo 請求,檢測其響應特徵。第三組測試是 U1,發送一個 UDP 包給一個關閉的端口,而後看下 ICMP 的 port unreachable 回覆。第四組測試是 ECN,全稱是 Explicit Congestion Notification,即「顯式擁塞通知」。該測試會發送帶 ECN 位的 TCP 請求,比較其響應。最後一組是發送六個不一樣的 TCP 包,這六個 TCP 包的響應結果將對應T2到T7的各項指標,其中 T2-T4 會發給打開的 TCP 端口,T5-T7 會發給關閉的 TCP 端口。