Nmap-服务探测

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liuxingen/article/details/45695365

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 sendmail-bugs@sendmail.org.
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都执行了。
展开阅读全文

没有更多推荐了,返回首页