端口扫描是Nmap的核心功能,Nmap支持多种扫描方式,不同的扫描方法具有探测原理不一致,且实现的效果不同。在有的网络环境中,汇总查看各种扫描方法的结果能够探测更为准确的主机信息。在命令行中可以使用
-s<C>
选项指定端口扫描的方法,除-sU
之外,其它几个扫描选项不能混用。
在Nmap当中大多数扫描方式需要操控原始的IP数据包,因此需要具有root/Administrator权限。如果没有对应的权限,有些Nmap会采用socket三次连接的方式替代不同的扫描方法,达到相同的扫描效果,需要发送更多的数据包。
端口状态
在Nmap当中扫描的端口被分成:open,closed,filtered,unfilterd,open|filtered,closed|filtered 六种状态。同一个扫描方法中不会同时存在这6种状态,每种状态会因为扫描方式的不同返回不同的结果。
open
open表示端口处于开启状态,说明有应用程序正在监听该端口。该端口能够接收TCP或者UDP数据包,同时对接收到的数据包做出响应。
closed
closed表示端口处于关闭状态,说明没有应用程序监听该端口。
filtered
filtered表明该端口没有任何的响应数据包,或者发送的探测帧被拦截,未能到达目的端口。或者端口有响应,但是响应的数据包全是ICMP错误信息(目标不可达:通信被管理员禁止)。此时有可能扫描主机与目标主机之间有防火墙,防火墙丢弃了所有的扫描或响应帧。注意:网络不通或IP未启用也会出现全端口被过滤的情况。
unfiltered
unfilter状态不是在所有扫描方法中都会存在,unfilter表明端口能够接收数据包,但是无法判断端口时开启还是关闭状态。使用Ack方式扫描时会出现处于该状态的端口。
open|filtered
open|filtered 表明nmap无法判断端口是处于开启状态还是处于过滤状态。只有在特定的扫描方式下会出现该种状态的端口。如UDP扫描、IP协议扫描、FIN、NULL、Xmax扫描均会出现这种状态的端口。
closed|filtered
表明nmap无法判断端口是处于关闭状态还是处于过滤状态,只有在特定的扫描方式下才会出现该种状态的端口。如IPID Idle扫描。
扫描方法
Nmap支持TCP/UDP两种协议的端口扫描方法。同时UDP扫描时可以结合使用TCP扫描。
SYN Scan
命令行选项: -sS
Nmap默认使用该种方式进行扫描。SYN扫描利用了TCP三次接时的第一次连接,通过发送设置了SYN标注的探测帧去扫描目标主机的端口,此时目标主机的端口会被分为三中状态:open、filtered、closed。
- opend: 目标主机正常响应三次连接的数据帧。即响应设置了SYN/ACK标志位的数据帧。
- closed: 此时目标主机响应RST帧
- filtered: 目标主机没有任何响应,或者响应的是ICMP不可达的错误消息(Type3,code 1,2,3,9,10 or 13)
优点: 快速、隐蔽(目标主机不会发现扫描主机的连接记录)、通用TCP Scan
命令行选项:-sT
TCP扫描就是利用系统的三次连接对目标主机的端口进行扫描。当Nmap不是以root/Administrator权限启动时,就会使用TCP扫描。扫描的端口状态与SYN扫描类似: - open: 目标主机正常响应三次连接的数据帧。即响应设置了SYN/ACK标志位的数据帧。
- closed: 此时目标主机响应RST帧
- filtered: 目标主机没有任何响应,或者响应的是ICMP不可达的错误消息(Type3,code 1,2,3,9,10 or 13)
UDP Scan
命令行选项:-sU
UDP扫描是Nmap扫描选项中唯一一个可以与其它扫描选项共用的扫描选项。对于大多数UDP端口,Nmap会向目标端口发送一个空的UDP数据包。但是对于常用且知名的UDP端口,Nmap会发送指定协议的数据包。根据端口的响应,Nmap会将端口分为四个状态: - open: UDP端口有响应数据包
- open|filtered: 无任何响应
- closed: ICMP 不可达响应(Type3,Code 3)
- filtered: 其它的ICMP不可达响应(type 3, code 1, 2, 9, 10, or 13)
不同的UDP端口使用的数据包结构往往不一致。而且UDP是无状态的,这就导致Nmap无法发送一个统一的数据包进行探测。为了探测一些知名的服务,Nmap需要使用一个数据库来存储每个知名服务的探测帧格式,在nmap-service-probes
文件中,存储有这些数据。当启用版本探测(-sV/-A
)选项时,Nmap就会向所有处于open|filtered状态的端口发送探测帧。如果有端口对某一探测帧做出了响应,Nmap就会将端口的open|filtered状态更改为open(Nmap5.1之后启用UDP探测时,默认会向知名的UDP端口发送对应的探测数据帧)。因此可以结合使用-sV选项来探测主机UDP端口的状态。优化UDP的扫描速度
UDP扫描速度要比TCP的SYN扫描速度慢,因此可以利用Nmap的一些选项优化Nmap的扫描速度。 - 增加同时扫描主机的数量
利用--min-hostgroup
选项增加同时扫描主机的数量。 - 优化发送的探测帧
利用--version-intensity 0
选项减少Nmap发送的探测帧。当开启-sV选线时,Nmap会向处于open|filtered状态的端口发送大量的数据帧以识别端口是否处于open状态。而利用--version-intensity 0
选项,则Nmap只会发送最有可能的数据帧。 - 减少主机等待时间
由于主机对响应的ICMP消息有速率限制,因此无法对每一个探测帧快速的响应ICMP目标不可达的消息。可以利用--host-timeout
选项减少Nmap主机的等待时间,从而跳过扫描比较慢的主机。TCP FIN,NULL and Xmas Scan
FIN、NULL、Xmas扫描分别对应:-sF、-sN、-sX
选项
这三种扫描选项主要是根据TCP RFC中的一处实现细节来区分端口的状态。在RFC 793的65页中曾记录:如果关闭的端口收到不包含RST标志位的数据包,那么该端口就响应RST数据包。并且在下一页中写道,如果开放的端口收到了没有设置SYN、RST或ACK标志位的数据包,那么应该将其丢弃掉。因此可以将端口分为下面三种状态: - open|filtered: 端口无任何响应
- closed: 端口响应RST数据包
- filtered: 端口返回ICMP不可达错误消息(type 3, code 1, 2, 3, 9, 10, or 13)
优点:FIN、Null、Xmas扫描能够绕过无状态的防火墙。
缺点:1.并不是所有的操作系统都遵循RFC973,一些操作系统不论端口是否开启都回响应RST数据包。如大多数的Windows、Cisco设备、IMB OS/400。 2. 无法区分端口是open还是filtered。Ack Scan
扫描选项:-sA
与其它的扫描选项不同,ACK扫描不能区分端口是否开启,因为无论端口是开启还是关闭状态对于ACK扫描都会响应RST,此时Nmap会将端口标记为unfiltered状态。Ack扫描可以用来映射防火墙的规则,判断防火墙是否是有状态的,并判断被防火墙防护的端口。 - unfiltered: 端口响应RST数据包(无法判断端口是open还是closed)
- filtered: 端口未响应或者响应ICMP不可达消息(type 3, code 1, 2, 3, 9, 10, or 13)
Windows Scan
扫描选项:-sW
Windows Scan发送的扫描数据包与Ack Scan发送的数据包是一致的,只不过Windows Scan是通过判断返回数据包中Window Size的值来判断端口是否开启。一些系统中,开放端口会将RST响应数据包中的Windows Size设置为正值,而关闭的端口会将RST响应包中的Window Size设置为0。 - open: RST响应包中的Window Size为正值
- closed: RST响应包中的Window Size 为0
- filterd: 端口未响应或者响应ICMP不可达消息(type 3, code 1, 2, 3, 9, 10, or 13)
该扫描选项只能适用于互联网上的部分机器,因此扫描结果不是十分可靠,不应该完全相信该扫描结果。Maimon Scan
扫描选项:-sM
Uriel Maimon发现的扫描方法,根据RFC793文档,当系统接收到FIN/ACK探测帧时,无论端口是否开启操作系统都应该响应RST数据包,但是Uriel发现,大多数BSD系统中,如果端口是开启的,则会丢弃该数据包。现代操作系统很少存在该问题,现在一般所有操作系统都会返回RST数据包。 - open|filtered: 未收到任何响应数据包
- closed: 收到RST响应数据包
- filtered: 收到ICMP不可达的错误数据包
由于现代系统支持该扫描方法的比较少,因此扫描结果不是十分可靠。Idle Scan
扫描选项:-sI host1 Target
Idle扫描是一种完全的盲扫描,扫描机器无需使用自己的IP地址向目标主机发送数据包,通过侧信道攻击的方式来获取目标主机端口的开启情况。Idle扫描的原理如下:
网络中的IP数据包都有一个fragment identification number(IP ID)。许多操作系统每发送一个IP数据包该IPID字段就会加1(不会为每个目标主机单独创建一个IPID序列)。如果向主机发送一个设置了SYN/ACK标志位的数据包,无论端口是开启还是关闭,都会响应一个RST数据包。
因此找一个符合条件(IPID会依次增长,不会为每个主机单独设置一个IPID序列)的僵尸机,向该主机发送一个设置有SYN/ACK标志位的数据包,然后获取到当前的IPID,之后扫描主机构造一个源IP为僵尸主机的IP且设置有SYN标志位的数据包,发送给扫描的目标主机,这样如果端口开启的话,目标主机会像僵尸主机发送一个设置有ACK/SYN标志位的数据包(端口开启),僵尸机回复一个RST数据包,IPID加一。最后扫描主机再像僵尸机发送一个设置有ACK/SYN标志位的数据包,然后获取RST数据包中的IPID字段,通过读取IPID字段的值,判断目标主机的端口是否开启。端口如果开启了的话,IPID的值会比第一次记录的IPID的值加2,端口如果没有开启,则IPID的值会维持不变。
Nmap的实现方法要比上述的复杂,因为Nmap需要实现并发扫描,如果同时扫描多个端口,尽管可以知道有多少端口开启,但是无法知道主机开启的具体端口号。Nmap具体的实现方式为,先并发扫描多个(100)端口,如果发现了其中有N个端口开启,则使用二分法,查找这些开启的端口。
根据前面的描述可知,使用该扫描方法,会探测到两种端口状态: - open: 端口开启,目标主机向僵尸主机响应了SYN/ACK数据包
- closed| filtered: 目标主机未响应任何数据包
选择僵尸主机
使用该Idle扫描方法比较困难的是需要寻找一个符合条件的僵尸主机,而且除了满足IPID是全局增长的之外,与该主机通信的主机最好比较少,这样就能产生更少的噪音。
当向目标主机进行探测时,使用-O
选项开启了目标主机的系统探测并冗余输出-v
的话,会在输出的数据中看到系统IP ID的生成方法,例如会输出”IP ID Sequence Generation:Incremental”,如果输出的类型是Incremental或者Broken little-endian incremental的话,那么该主机就有可能成为僵尸主机。
另一个方法是扫描主机时运行ipidseq
NSE脚本,这个脚本会探测目标主机IP ID的生成方法。
该种扫描方式还可以用来探测IP之间的信任关系,例如某些主机仅允许固定来源的IP数据包进入。主要如果为了隐蔽,还需要使用-Pn
选项,否则目标主机还是会收到扫描主机的IP。
IP Protocol Scan
扫描选项: -sO
(是字母O不是数字零)
IP协议扫描不是扫描主机的端口,而是探测目标主机支持的IP协议。通过不断更改IP数据包中代表协议的标号,构造探测帧并发送给目标主机,来探测目标主机支持的协议。此时-p
选项不再是表明的端口号,而是表明的协议号。
- open: 构造的协议有响应
- closed: ICMP不可达消息(type 3, code 2)
- filtered: 其它的ICMP不可达响应(type 3, code 1, 3, 9, 10, or 13)
- open|filtered: 无任何响应(重发之后也每任何响应)
可以利用该种扫描方式来判断主机的作用,如路由器或其它设备FTP Bounce Scan
扫描选项:-b
之前的Ftp服务器允许用户连接至Ftp服务器,并要求该服务器向第三方服务器发送文件,返回的错误消息可以判断端口是否开启,因此利用这种方式可以探测目标主机的端口状态。
使用方法为:-b <username>:<password>@<Ftp_Server>:<port> <Target_Server>
时间消耗相关的参数
Nmap扫描过程中,端口扫描会占据较长的时间。Nmap提供了命令选项来设置一些数据的超时时间。大部分选项的默认时间单位是秒,不过也可以自定指定单位,如m(毫秒),s(秒),m(分钟),h(小时)-T0
到-T5
-T0
到-T5
代表6个提前定义好的时间模板,-T0
代表最慢,-T5
代表最激烈。
探测帧从发出到收到该帧的响应时间为一个数据帧的RTT时间。--min-rtt-timeout
--max-rtt-timeout
--initial-rtt-timeout
--min-rtt-timeout
--max-rtt-timeout
--initial-rtt-timeout
分别表示Nmap等待响应帧的最小、最大和初始时间。使用Nmap进行扫描时,可以先用Ping命令探测一下基本的RTT时间,然后手动指定一下--max-rtt-timeout
和--initial-rtt-timeout
Nmap等待一个主机响应的最长时间,如果超过这个时间,Nmap将会放弃对该主机的扫描。主机发现是使用。--host-timeout
设置Nmap每秒钟发送探测帧的数量--min-rate
--max-rate
设置Nmap对某个端口探测帧的重发次数。--max-retries
设置Nmap一次扫描的最小、最大主机数。--min-hostgroup
--max-hostgroup
设置Nmap扫描主机端口的最小、最大并发数。可以理解为一次扫描多少个端口(不一定是同一个主机的)--min-parallelism
--max-parallelism
设置Nmap在探测另一个主机时等待的时间数,如果Nmap检测到数据包丢失,会增加等待时间,但是该时间会一直增加到指定的--scan-delay
--max-scan-delay
--max-scan-delay
提高Nmap扫描速度的技巧
在扫描主机时,可以分别利用-Pn
和-n
选项关闭对主机的Ping
扫描和反向DNS
查询,同时根据手动ping
的结果设置等待探测帧的时间。该方法不适合探测多个主机。输出选项
增加nmap输出的冗余级别,会让nmap输出更多的信息。多个v同时使用会增加输出的冗余级别。-v
增加调试级别,会使nmap输出更多的信息。有9个级别,可以了解nmap的工作机制。-d
输出nmap接收或发送的数据包。--packet-trace
普通输出,-oN
Xml格式输出-oX
grepable 格式输出。-oG
全格式输出,所有的格式均会输出一份文件。-oA
利用通过--resume
-oN
或-oG
输出的文件恢复扫描。除--resume
之外,无需指定其它任何选项。
将nmap的输出追加至--append-output
-oN
或-G
指定的文件当中。
只显示具有开放端口(可能是开放端口的主机:open,open|filtered,unfiltered)的主机,并显示主机开放的端口。--open
例子:-oG logs/pb-port80scan-%D.gnmap
: %D选项表明输出的日期。1
nmap -T4 -Pn -p80 --max-rtt-timeout 200ms --initial-rtt-timeout 150ms --min-hostgroup 512 -oG logs/pb-port80scan2-%D.gnmap 216.163.128.0/20
通过指定--initital-rtt-timeout
和--min-hostgroup
选项缩短了扫描时间。rtt-time是设置一个数据包的来回时间,系统通过RTTtime来判断数据的重发时间。
Nmap端口扫描算法相关
Nmap在扫描时会在内存中记录发出的每个探测帧,然后再通过与该探测帧对应的响应帧获取网络环境信息,从而实时调整Nmap的发包策略。如Nmap会记录每个数据包的RTT time,然后计算除srtt,然后计算每次srtt的偏差,如果偏差较小,这就说明网络状况比较稳定,Nmap会等待数据帧srtt的时间。反之,如果偏差较大,这就说明网络状况较差,此时Nmap等待的时间就会变长。
总结
在所有的扫描方法种,只有-sS
该种扫描方式最为快速,隐蔽,可靠。其它扫描方法都或多或少存在一些问题,且输出的状态不是特别清楚,之后再某些有限的条件下, 配合sS
进行使用。再使用其他扫描方式时,需要考虑该扫描方式的不可靠性。适当的为Nmap添加一些参数能够缩短Nmap的扫描时间。