Nmap开篇之功能和原理简介

写在前面

终于开始了Nmap这个系列. 算是作为渗透测试这个分类的开端. 这些天厌倦论文, 换个大脑思维模式的时候, 开始尝试去读源代码, 开始去理解这个工具背后的设计原理. 手上并没有什么关于Nmap的中文书籍, 也没法从国内运过来. 身在这个所谓”尊重知识”的国度, 买书是我这个人生阶段所承受不起的. 好在, 从学校的图书馆资源中, 发现了一本比较新的书, 并且提供了在线版本.

Nmap: Network Exploration and Security Auditing Cookbook(By Paulino Calderon, 2nd Edition, 2017.5.26)

从入学开始到现在, 图书馆在书籍在线化工作的确做了不少工作. 本系列部分内容也会参考于这本书.

演示模拟测试平台

不仅仅是基于安全的考虑, 更多的是基于隐私的考虑, 这个系列的文章中并不会去扫描真实的网络. 实话说, 也是会担心, 这种操作是不是会违反了学校的某个网络使用条例, 会不会被学校CSSD的人发觉, 然后被约谈. 当然, 更多的是隐私考虑, 作为一个安全领域的工作者, 隐私某种程度上也算是第二生命, 保护好自己的隐私, 也不去泄露别人的隐私, 算是一种很好的美德.

基于上述考虑, 后续演示, 会基于一个模拟平台完成. 简单来说, 会在VirtualBox中开两个虚拟机: Kali-Linux-2018.1和Kioptrix-Level-1. 这里不去多介绍Kali-Linux, 应该算是当前很著名的瑞士军刀般的用来做渗透测试系统, 后续应该还会开一个系列去介绍. Kioptrix是一个开放了某些服务, 并且带有漏洞的一个简易版的Linux服务器, Level-1则表示这是一个入门级别的靶机.

总结下,

  • Kali和Kioptrix会被设定在同一个NAT虚拟网段中, 确保他们之间是可以互相连接的.
  • Kali视作一个攻击方, Kali中集成了Nmap工具, 本文中涉及的Nmap是7.7版本, 也是写这篇文章为止, 最新的稳定版.
  • Kioptrix视作一个被攻击方, 相当于一个靶场.

Nmap从这里开始

Nmap简介

Nmap, 全称Network Mapper, 网络映射器, 是一款用于网络发现的安全审计工具. 简单来说, Nmap可以罗列网络上的主机清单, 监控主机服务及其运行情况.

忽略黑客工具这个背景, Nmap可以作为给网络工具帮助网络管理者识别所在网络中未经批准的服务器. 而事实上, 它更多的是作为黑客, 或者说渗透测试者, 用来搜集目标主机的网络设定, 进而下一步可以根据搜集的信息实施进一步的攻击方案. 再次说明, Nmap通常用在渗透测试的情报搜集阶段, 并不是直接的攻击工具. 它的扫描结果, 可以集成或者被其他攻击工具, 比如说Metasploit框架, 使用. Nmap不仅可以扫描单个主机, 也可以扫描某个网段内的主机, 即大规模的网络.

Nmap之主机发现

主机发现(Host Discovery)的主要目标是确认目标主机是否在线.

如果让你来确认一个目标主机是否在线, 通常第一个在脑中浮现的方法应该是Ping命令. 比如下面这条命令.

1
2
3
4
5
6
7
8
9
root@kali:~# ping -c 3 www.google.com
PING www.google.com (172.217.15.68) 56(84) bytes of data.
64 bytes from iad23s63-in-f4.1e100.net (172.217.15.68): icmp_seq=1 ttl=51 time=8.74 ms
64 bytes from iad23s63-in-f4.1e100.net (172.217.15.68): icmp_seq=2 ttl=51 time=8.95 ms
64 bytes from iad23s63-in-f4.1e100.net (172.217.15.68): icmp_seq=3 ttl=51 time=8.98 ms

--- www.google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 8.746/8.894/8.981/0.151 ms

上面的结果可以看出google的172.217.15.68这个主机是存活的. Nmap的主机发现原理与上述Ping命令类似, 也就是通过发送探测数据包到目标主机. 如果收到回复, 那么目标主机就是开启状态. 与Ping命令不同的是, Nmap使用或者支持更多的探测方式, 而不仅仅像Ping命令中的ICMP数据包.

在默认情况下, Nmap会发送四个不同类型的数据包(ICMP Echo, TCP SYN, TCP ACK, ICMP Timestamp)来探测一个目标主机是否在线. 只要其中给一个数据包收到回复, 那么就可以确认该目标主机存活. 只所以使用不同类型的数据包去探测, 主要是考虑目标主机可能存在防火墙, 某些防火墙规则可能限制主机对于一些探测数据包做出相应. 上述设定正式为了防止误判.

一个使用Nmap进行主机发现的典型例子.

1
2
3
4
5
6
root@kali:~# nmap -sn 10.0.2.5
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-19 19:18 EDT
Nmap scan report for 10.0.2.5
Host is up (0.00037s latency).
MAC Address: 08:00:27:F8:6F:34 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 0.13 seconds

这里-sn表示只使用Nmap进行主机发现而不进行后续的端口扫描. 另外一个常用的选项是-Pn, 表示跳过主机发现步骤, 默认所在主机已经开启, 而直接进行端口扫描. 当然更多的选项这里就不列举了, 因为我也没记住那么多的选项和含义. 需要用的时候, 可以查看帮助nmap –help.

备注: 一般在广域网中, Nmap使用上述手段来探测, 而在局域网中, Nmap则只需要使用ARP数据包来探测即可.

Nmap之端口扫描

在上述探测到目标主机在线(存活)的状态后, 下一步自然就是探测目标主机开放了哪些端口, 也就是这里说的端口扫描功能. 具体来说, 就是确定目标主机的TCP和UDP端口的具体开放状态.

如果不指定扫描的端口范围, 默认情况下, Nmap会自动扫描默认的最有可能的开放端口, 大概在1000个左右. 完成扫描之后, Nmap会根据结果给某个具体的端口划分如下6个状态: Open (开放状态); Closed (关闭状态); Filtered (端口被防火墙, IPS或者IDS屏蔽, 状态不确定); Unfiltered (端口没有屏蔽, 但是具体状态不确定). 最后两种结果则表达为 Open|Filtered 和 Closed|Filtered, 两种状态的组合, 可以理解为Nmap根据结果在Filtered和UNfiltered之间的状态的某种猜测.

端口扫描可以算是Nmap最具核心和特色的功能. 因此, 它提供的端口探测方式也十分丰富. 这里简单列举两种方式来说明端口扫描的原理.

TCP SYN 扫描

TCP SYN扫描应该是Nmap的默认扫描方式. 该扫描方式, 发送一个TCP SYN数据包到目标端口, 如果收到了TCP SYN/ACK回复的话, 则可以判定该端口是开放的. 反之, 如果收到的是RST回复数据包, 则可以判定该端口是关闭的. 还有一种情况就是没有收到目标主机端口回复的数据包, 那么一般可以判定为Filtered, 端口被屏蔽. 上述可以看出, TCP连接没有完成, 毕竟没有完成三次握手, 但是了解到了特定端口的状态. 因此可以归纳为半开放式扫描. 这种扫描的好处就是比较隐蔽, 同时不建立完整的TCP连接, 效率比较高.

TCP ACK 扫描

Nmap使用 TCP协议向目标端口发送ACK数据包, 如果收到了RST数据包, 则说明该端口没有被防火墙/IPS/IDS屏蔽, 如果没有收到RST数据包, 则说明被屏蔽了. 这种扫描方式可以用来探测防火墙是否屏蔽了某些端口, 通过和上述的TCP SYN扫描方式来判断目标主机防火墙/IDS/IPS的状态.

端口扫描的使用

上述只是用了两种扫描方式来举例说明端口扫描的原理. 这里简单介绍下如何使用Nmap的扫描端口功能. 下面是一个典型的端口扫描示例.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@kali:~# nmap -sS -sU -T4 10.0.2.5
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-19 20:08 EDT
Nmap scan report for 10.0.2.5
Host is up (0.00037s latency).
Not shown: 1938 closed ports, 54 open|filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
443/tcp open https
32768/tcp open filenet-tms
111/udp open rpcbind
137/udp open netbios-ns
MAC Address: 08:00:27:F8:6F:34 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 1306.01 seconds

这里选项-sS指定了扫描方式选用TCP SYN方式, -sU表示使用了UDP扫描方式, -T4则指定了扫描过程使用的时序, 总共6个级别(0-5), 级别越高, 扫描越快, 但是坏处是容易被IDS或者防火墙检测到, 进而屏蔽该扫描.

上述结果我们可以看出, 目标主机, 也就是上述描述的模式测试平台中的Kioptrix-Level-1开放了常用的22端口(ssh服务), 80端口(Http服务). 还有137/udp端口(通常是NetBIOS的名称服务).

另外这里没有演示另外一个常用的选项, -p, 可以用来指定扫描的端口范围, 比如, -p80表示只扫描80端口, -p22-100表示只扫描22-100这个范围的端口.

Nmap之服务版本检测

服务版本检测指的是监听某个特定端口的服务所使用的具体版本信息. 举个例子说, 目标主机支持Web服务, 并且Web服务器使用的Nginx 1.14.0版本, 那么Nmap版本检测的目标就是, 通过扫描Web服务的80端口, 检测到使用的Web服务是Nginx, 并且进一步检测到Nginx的版本为1.14.0.

一个简单的问题就是, 可能会问检测到版本的意义何在. 那么从渗透测试的角度来说, 如果攻击者知道了版本信息, 可以为下一步的攻击方式提供很多方案. 比如如果我们知道了目标主机运行的是Nginx 1.14.0服务器, 那么我可以搜索查看, 是否有已经公布的Nginx在1.14.0这个版本上的漏洞, 进而可以直接利用. 退一步说, 如果对目标主机志在必得, 那么知道了版本信息, 我们可以直接研究1.14.0版本这个Nginx的源码, 自己去发掘是否有存在的漏洞. 毕竟Nginx是一个开源服务器软件. 当然, 前者是给小白黑客使用的, 后者则可能算是黑客的精髓. 类似于挖掘到了一个0day漏洞, 当然一个0day价值是不菲的, 特别是知名且被广泛应用的软件或者操作系统上挖掘的.

有点扯远了, 回到版本检测这个话题上. 简单来说, Nmap的版本检测就是通过给端口的服务发送请求, 然后和应用程序数据库(nmap-service-probes)对比服务的签名来确定服务的版本.

稍微具体来说, 在端口扫描的基础上, 在开发的端口列表中, 尝试建立连接. 如果是TCP端口, 则发送TCP连接, 然后等待片刻. 根据在等待片刻内, 收到的目标主机的”WelcomeBanner”信息来和nmap-service-probes中的NULL probe中的签名进行对比, 进而得到应用程序的名字和版本信息. 如果通过上述的”WelcomeBanner”信息没法确认, 再根据nmap-service-probes中挑选合适的probe, 然后发送探测包, 进而通过收到的回复包进行签名对比. 最差的情况是, 反复探测没有发现可对比的签名, 那么Nmap会打印收到的报文, 由用户自己来判断. 当然, UDP端口, 探测原理也是类似的.

值得一提的是, 如果检测到目标程序是SSL, Nmap会使用openSSL来进一步检测, 运行在SSL上的具体应用类型.

这里展示一个版本检测的示例. 版本检测的选项是 -sV.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@kali:~# nmap -sS -sU -p1-500 -sV 10.0.2.5
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-19 21:04 EDT
Nmap scan report for 10.0.2.5
Host is up (0.00035s latency).
Not shown: 992 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 2.9p2 (protocol 1.99)
80/tcp open http Apache httpd 1.3.20 ((Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b)
111/tcp open rpcbind 2 (RPC #100000)
139/tcp open netbios-ssn Samba smbd (workgroup: MYGROUP)
443/tcp open ssl/https Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b
111/udp open rpcbind 2 (RPC #100000)
137/udp open netbios-ns Samba nmbd netbios-ns (workgroup: MYGROUP)
138/udp open|filtered netbios-dgm
MAC Address: 08:00:27:F8:6F:34 (Oracle VirtualBox virtual NIC)
Service Info: Host: KIOPTRIX
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 598.82 seconds

对比端口扫描中的结果, 这里只扫描1-500端口, 并且添加了版本检测的需求 -sV. 其中扫描结果多了一份VERSION信息. 比如ssh服务, 这里识别出了Kioptrix中使用的是OpenSSH 2.9p2版本. 另外, 开放在443上的https服务, 显示的是Apache/1.3.20 (Unix) (Red-Hat/Linux) mod_ssl/2.8.4 OpenSSL/0.9.6b, 可以了解到使用的Apache httpd软件的1.3.20版本, 通过mod_ssl/2.8.4, 结合了OpenSSL/0.9.6b.

Nmap之操作系统检测

通常渗透测试进入一台目标主机, 可以通过应用程序的漏洞攻入, 也可以通过操作系统的漏洞进入目标主机. 这样一来, 就需要搜集到目标主机的操作系统类型, 操作系统版本, 操作系统内核的版本等等. Nmap也提供了系统检测功能, 可以用来检测目标主机的系统信息和设备类型等等.

和上述的应用服务版本检测类似, Nmap也维护一个nmap-os-db数据库, 存储了上千种操作系统信息. 简单一点来说, Nmap通过TCP/IP协议栈的指纹信息来识别目标主机的操作系统信息. 这主要是利用了RFC标准中, 没有强制规范了TCP/IP的某些实现, 于是不同的系统中TCP/IP的实现方案可能都有其特定的方式, 这些细节上的差异, 给nmap识别操作系统信息提供了方案. 具体一点说, Nmap分别挑选一个close和open的端口, 分别发送给一个经过精心设计的TCP/UDP数据包, 当然这个数据包也可能是ICMP数据包. 然后根据收到返回报文, 生成一份系统指纹. 通过对比检测生成的指纹和nmap-os-db数据库中的指纹, 来查找匹配的系统. 最坏的情况下, 没有办法匹配的时候, 则用概率的形式枚举出所有可能的信息.

这里展示一个系统版本检测的示例.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@kali:~# nmap -O 10.0.2.5
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-19 21:26 EDT
Nmap scan report for 10.0.2.5
Host is up (0.00033s latency).
Not shown: 994 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
443/tcp open https
32768/tcp open filenet-tms
MAC Address: 08:00:27:F8:6F:34 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 2.4.X
OS CPE: cpe:/o:linux:linux_kernel:2.4
OS details: Linux 2.4.9 - 2.4.18 (likely embedded)
Network Distance: 1 hop
OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 1.82 seconds

系统版本检测需求使用-O来指定. 上述结果可以看出Kioptrix-Level-1使用的Linux 2.4.X内核版本的Linux系统.

这里再展示一下扫描我个人VPS的结果示例, 扫描结果会用概率形式枚举. 当然我会屏蔽一些个人信息.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@kali:~# nmap -O [xxx.com]
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-19 21:28 EDT
Nmap scan report for xurunhua.com (192.155.86.91)
Host is up (0.057s latency).
rDNS record for [xx.xx.xx.xx]: [xxx.xxxx.xxx.com]
Not shown: 997 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Device type: VoIP phone|webcam|firewall|specialized|general purpose
Running (JUST GUESSING): Grandstream embedded (90%), Garmin embedded (88%), FireBrick embedded (87%), 2N embedded (87%), Cognex embedded (85%), lwIP (85%)
OS CPE: cpe:/h:grandstream:gxp1105 cpe:/h:garmin:virb_elite cpe:/h:firebrick:fb2700 cpe:/h:2n:helios cpe:/a:lwip_project:lwip
Aggressive OS guesses: Grandstream GXP1105 VoIP phone (90%), Garmin Virb Elite action camera (88%), FireBrick FB2700 firewall (87%), 2N Helios IP VoIP doorbell (87%), Cognex DataMan 200 ID reader (lwIP TCP/IP stack) (85%)
No exact OS matches for host (test conditions non-ideal).

OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.03 seconds

上述结果中中括号内[xxx]的信息已经屏蔽. 结果显示Running (JUST GUESSING)信息. 上述信息可以看出, 我的VPS提供商, 在操作系统信息上, 做了很多模糊策略, Nmap检测到大概率判断居然是一台VoIP phone 或是其他的IoT硬件, 并没有泄露出主机的操作系统信息.

Nmap之一些高级应用

这里并不详细论述高级应用的使用情况. 简短介绍一下, Nmap的另外两个高级功能: 防火墙/IDS规避和哄骗, 以及NSE脚本引擎.

防火墙/IDS规避和哄骗

在上述的介绍中, 我们以及了解到Nmap会遭遇到防火墙/IDS系统的屏蔽和保护, 进而没有办法获取到主机的运行情况. 因此Nmap也提供一些高级功能, 供用户去绕开或者规避防火墙/IDS系统的检测.

其基本的原理和方法就是: 转换数据包, 或者 改变数据包发送时机.

举例来说, 可以将可以的数据包分片(fragmentation)处理, 一个TCP数据包, 拆分为多个IP包发送出去. 实际应用环境中, 某些防火墙为了提高数据处理效率, 可能会适时放弃一些功能, 比如重组数据检查. 如此可以达到绕过防火墙检测的目的. 另一个例子是, 通过IP诱骗或者伪装, 在扫描的时候, 将真实IP和其他主机IP混合使用, 或者直接伪装成其他IP地址, 或者使用匿名网络Tor等, 防止目标主机的防火墙或者IDS系统, 统计分析检测到本次扫描. 简而言之, 就是通过IP诱骗伪装的方式, 使得目标主机认为扫描过程中发起的各种数据包请求是正常用户的数据包请求.

改变发送数据包时机, 也可以归结为延时扫描. 有些防火墙会通过分析识别出频繁发送的数据包, 进而严格检查这些数据包. 为此, 通过定制不同的数据包发送频率和发送延时来欺骗目标主机防火墙.

当然各种伪装技术不能在这里一一列举出来. 本质上来说, 就是根据目标主机防火墙或者IDS系统的策略, 来定制反制策略, 来达到伪装成正常用户数据请求的目的.

NSE脚本引擎

NSE脚本引擎, 也是Nmap最强大和灵活的功能之一. 那就是允许用户自己编写脚本来自动化执行某些Nmap的功能, 进而可以扩展Nmap. NSE使用的Lua脚本语言. Nmap也提供了一些由社区贡献出来的脚本库供用户使用.

这里不再更多的论述. 毕竟平时的单机测试, 使用简单shell命令就可以完成需求. NSE脚本更适合大规模搜集互联网信息, 脚本化或者自动执行某些Nmap任务需求的场景.

写在最后

下一次更新, 可能会依托Nmap源码, 进一步展示上述各个模块的功能如何体现在代码实现中.

坚持技术分享,你的支持将鼓励我继续创作!
0%