Nmap学习笔记之端口扫描

端口扫描是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的话,那么该主机就有可能成为僵尸主机。
    另一个方法是扫描主机时运行ipidseqNSE脚本,这个脚本会探测目标主机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代表最激烈。

    --min-rtt-timeout --max-rtt-timeout --initial-rtt-timeout

    探测帧从发出到收到该帧的响应时间为一个数据帧的RTT时间。--min-rtt-timeout --max-rtt-timeout --initial-rtt-timeout分别表示Nmap等待响应帧的最小、最大和初始时间。使用Nmap进行扫描时,可以先用Ping命令探测一下基本的RTT时间,然后手动指定一下--max-rtt-timeout--initial-rtt-timeout

    --host-timeout

    Nmap等待一个主机响应的最长时间,如果超过这个时间,Nmap将会放弃对该主机的扫描。主机发现是使用。

    --min-rate --max-rate

    设置Nmap每秒钟发送探测帧的数量

    --max-retries

    设置Nmap对某个端口探测帧的重发次数。

    --min-hostgroup --max-hostgroup

    设置Nmap一次扫描的最小、最大主机数。

    --min-parallelism --max-parallelism

    设置Nmap扫描主机端口的最小、最大并发数。可以理解为一次扫描多少个端口(不一定是同一个主机的)

    --scan-delay --max-scan-delay

    设置Nmap在探测另一个主机时等待的时间数,如果Nmap检测到数据包丢失,会增加等待时间,但是该时间会一直增加到指定的--max-scan-delay

    提高Nmap扫描速度的技巧

    在扫描主机时,可以分别利用-Pn-n选项关闭对主机的Ping扫描和反向DNS查询,同时根据手动ping的结果设置等待探测帧的时间。该方法不适合探测多个主机。

    输出选项

    -v

    增加nmap输出的冗余级别,会让nmap输出更多的信息。多个v同时使用会增加输出的冗余级别。

    -d

    增加调试级别,会使nmap输出更多的信息。有9个级别,可以了解nmap的工作机制。

    --packet-trace

    输出nmap接收或发送的数据包。

    -oN

    普通输出,

    -oX

    Xml格式输出

    -oG

    grepable 格式输出。

    -oA

    全格式输出,所有的格式均会输出一份文件。

    --resume

    利用通过-oN-oG输出的文件恢复扫描。除--resume之外,无需指定其它任何选项。

    --append-output

    将nmap的输出追加至-oN-G指定的文件当中。

    --open

    只显示具有开放端口(可能是开放端口的主机:open,open|filtered,unfiltered)的主机,并显示主机开放的端口。
    例子:
    -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的扫描时间。