七、 端口扫描技术

作为一个修车新手,我可能折腾几个小时来摸索怎样把基本工具(锤子,胶带,扳子等) 用于手 头的任务。当我惨痛地失败,把我的老爷车拖到一个真正的技师那儿的时候,他总是在他的工 具箱里翻来翻去,直到拽出一个完美的工具然后似乎不费吹灰之力搞定它。端口扫描的艺术和 这个类似。专家理解成打的扫描技术,选择最适合的一种 (或者组合)来完成给定的任务。 另 一方面,没有经验的用户和刚入门者总是用默认的 SYN 扫描解决每个问题。既然 Nmap 是免费的 掌握端口扫描的唯一障碍就是知识。这当然是汽车世界所不能比的,在那里,可能需要高超的 技巧才能确定您需要一个压杆弹簧压缩机,接着您还得为它付数千美金。

大部分扫描类型只对特权用户可用。这是因为他们发送接收原始报文,这在 Unix 系统需要 root 权限。在 Windows 上推荐使用 administrator 账户,但是当 WinPcap 已经被加载到操作系统时 非特权用户也可以正常使用 Nmap 当 Namp 在 1997 年发布时 需要 root 权限是一个严重的局限 因为很多用户只有共享的 shell 账户。现在,世界变了,计算机便宜了,更多人拥有互联网连 接,桌面 UNIX 系统 (包括 Linux 和 MAC OS X)很普遍了。Windows 版本的 Nmap 现在也有了,这 使它可以运行在更多的桌面上。由于所有这些原因,用户不再需要用有限的共享 shell 账户运 行 Nmap。这是很幸运的,因为特权选项让 Nmap 强大得多也灵活得多。

虽然 Nmap 努力产生正确的结果,但请记住所有结果都是基于目标机器(或者它们前面的防火墙) 返回的报文的。。这些主机也许是不值得信任的,它们可能响应以迷惑或误导 Nmap 的报文。更 普遍的是非 RFC 兼容的主机以不正确的方式响应 Nmap 探测。FIN,Null 和 Xmas 扫描特别容易遇 到这个问题。这些是特定扫描类型的问题,因此我们在个别扫描类型里讨论它们。

这一节讨论 Nmap 支持的大约十几种扫描技术。一般一次只用一种方法,除了 UDP 扫描(-sU)可 能和任何一种 TCP 扫描类型结合使用 友情提示一下 端口扫描类型的选项格式是-sC 其中 C 是 个显眼的字符,通常是第一个字符。一个例外是 deprecated FTP bounce 扫描(-b)。默认情况 下,Nmap 执行一个 SYN 扫描,但是如果用户没有权限发送原始报文(在 UNIX 上需要 root 权限) 或者如果指定的是 IPv6 目标,Nmap 调用 connect()。本节列出的扫描中,非特权用户只能执行 connect()和 ftp bounce 扫描。

-sS (TCP SYN 扫描)

SYN 扫描作为默认的也是最受欢迎的扫描选项,是有充分理由的。它执行得很快,在一个 没有入侵防火墙的快速网络上,每秒钟可以扫描数千个端口。 SYN 扫描相对来说不张扬 不易被注意到,因为它从来不完成 TCP 连接。它也不像 Fin/Null/Xmas,Maimon 和 Idle 扫描依赖于特定平台,而可以应对任何兼容的 TCP 协议栈。它还可以明确可靠地区分 open(开放的), closed(关闭的),和 filtered(被过滤的) 状态

它常常被称为半开放扫描,因为它不打开一个完全的 TCP 连接。它发送一个 SYN 报文, 就像您真的要打开一个连接,然后等待响应。 SYN/ACK 表示端口在监听 (开放),而 RST (复位)表示没有监听者。如果数次重发后仍没响应,该端口就被标记为被过滤。如果收 到 ICMP 不可到达错误 (类型 3,代码 1,2,3,9,10,或者 13),该端口也被标记为被 过滤。

-sT (TCP connect()扫描)

当 SYN 扫描不能用时,CP Connect()扫描就是默认的 TCP 扫描。当用户没有权限发送原 始报文或者扫描 IPv6 网络时,就是这种情况。 Instead of writing raw packets as most other scan types do,Nmap 通过创建 connect() 系统调用要求操作系统和目标机以及 端口建立连接,而不像其它扫描类型直接发送原始报文。 这是和 Web 浏览器,P2P 客户 端以及大多数其它网络应用程序用以建立连接一样的 高层系统调用 它是叫做 Berkeley Sockets API 编程接口的一部分。Nmap 用该 API 获得每个连接尝试的状态信息,而不是 读取响应的原始报文。

当 SYN 扫描可用时,它通常是更好的选择。因为 Nmap 对高层的 connect()调用比对原始 报文控制更少 所以前者效率较低 该系统调用完全连接到开放的目标端口而不是像 SYN 扫描进行半开放的复位。这不仅花更长时间,需要更多报文得到同样信息,目标机也更 可能记录下连接。IDS(入侵检测系统)可以捕获两者,但大部分机器没有这样的警报系统 当 Nmap 连接,然后不发送数据又关闭连接,许多普通 UNIX 系统上的服务会在 syslog 留 下记录,有时候是一条加密的错误消息。此时,有些真正可怜的服务会崩溃,虽然这不 常发生。如果管理员在日志里看到来自同一系统的一堆连接尝试,她应该知道她的系统 被扫描了。

-sU (UDP 扫描)

虽然互联网上很多流行的服务运行在 TCP 协议上,UDP 服务也不少。 DNS,SNMP,和 DHCP (注册的端口是 53,161/162,和 67/68)是最常见的三个。因为 UDP 扫描一般较慢,比 TCP 更困难,一些安全审核人员忽略这些端口。这是一个错误,因为可探测的 UDP 服务相当 普遍,攻击者当然不会忽略整个协议。所幸,Nmap 可以帮助记录并报告 UDP 端口。

UDP 扫描用-sU 选项激活 它可以和 TCP 扫描如 SYN 扫描 (-sS)结合使用来同时检查两种 协议。

UDP 扫描发送空的(没有数据)UDP 报头到每个目标端口。如果返回 ICMP 端口不可到达错 误(类型 3,代码 3),该端口是 closed(关闭的)。 其它 ICMP 不可到达错误(类型 3,代 码 1,2,9,10,或者 13)表明该端口是 filtered(被过滤的)。偶尔地,某服务会响应一 个 UDP 报文,证明该端口是 open(开放的)。如果几次重试后还没有响应,该端口就被认为是 open|filtered(开放|被过滤的)。这意味着该端口可能是开放的,也可能包过滤器 正在封锁通信。可以用版本扫描(-sV)帮助区分真正的开放端口和被过滤的端口。

UDP 扫描的巨大挑战是怎样使它更快速。开放的和被过滤的端口很少响应,让 Nmap 超时 然后再探测,以防探测帧或者响应丢失。关闭的端口常常是更大的问题。它们一般发回 一个 ICMP 端口无法到达错误 但是不像关闭的 TCP 端口响应 SYN 或者 Connect 扫描所发 送的 RST 报文,许多主机在默认情况下限制 ICMP 端口不可到达消息。 Linux 和 Solaris 对此特别严格。例如, Linux 2.4.20 内核限制一秒钟只发送一条目标不可到达消息 (见 net/ipv4/icmp。c)。

Nmap 探测速率限制并相应地减慢来避免用那些目标机会丢弃的无用报文来阻塞网络。不 幸的是,Linux 式的一秒钟一个报文的限制使 65,536 个端口的扫描要花 18 小时以上。 加速 UDP 扫描的方法包括并发扫描更多的主机,先只对主要端口进行快速扫描,从防火 墙后面扫描,使用--host-timeout 跳过慢速的主机。

-sN; -sF; -sX (TCP Null,FIN,and Xmas 扫描)

这三种扫描类型 (甚至用下一节描述的 --scanflags 选项的更多类型) 在 TCP RFC 中 发掘了一个微妙的方法来区分 open(开放的)和 closed(关闭的)端口。第 65 页说“如果 [目标]端口状态是关闭的.... 进入的不含 RST 的报文导致一个 RST 响应。” 接下来的 一页讨论不设置 SYN,RST,或者 ACK 位的报文发送到开放端口: “理论上,这不应该发 生,如果您确实收到了,丢弃该报文,返回。 ”

如果扫描系统遵循该 RFC,当端口关闭时,任何不包含 SYN,RST,或者 ACK 位的报文会 导致一个 RST 返回,而当端口开放时,应该没有任何响应。只要不包含 SYN,RST,或者 ACK,任何其它三种(FIN,PSH,and URG)的组合都行。Nmap 有三种扫描类型利用这一点

Null 扫描 (-sN) 不设置任何标志位(tcp 标志头是 0) FIN 扫描 (-sF)

只设置 TCP FIN 标志位。 Xmas 扫描 (-sX)

设置 FIN,PSH,和 URG 标志位,就像点亮圣诞树上所有的灯一样。

除了探测报文的标志位不同,这三种扫描在行为上完全一致。如果收到一个 RST 报文, 该端口被认为是 closed(关闭的) 而没有响应则意味着端口是 open|filtered(开放或者 被过滤的)。如果收到 ICMP 不可到达错误(类型 3,代号 1,2,3,9,10,或者 13),该 端口就被标记为 被过滤的。

这些扫描的关键优势是它们能躲过一些无状态防火墙和报文过滤路由器。另一个优势是 这些扫描类型甚至比 SYN 扫描还要隐秘一些。但是别依赖它 -- 多数现代的 IDS 产品可

以发现它们。一个很大的不足是并非所有系统都严格遵循 RFC 793。 许多系统不管端口 开放还是关闭,都响应 RST。这导致所有端口都标记为 closed(关闭的)。这样的操作系 统主要有 Microsoft Windows,许多 Cisco 设备,BSDI,以及 IBM OS/400。但是这种扫 描对多数 UNIX 系统都能工作 这些扫描的另一个不足是它们不能辨别 open(开放的)端口 和一些特定的 filtered(被过滤的)端口,从而返回 open|filtered(开放或者被过滤 的)。

-sA (TCP ACK 扫描)

这种扫描与目前为止讨论的其它扫描的不同之处在于它不能确定 open(开放的)或者 open|filtered(开放或者过滤的))端口。它用于发现防火墙规则,确定它们是有状态的 还是无状态的,哪些端口是被过滤的。

ACK 扫描探测报文只设置 ACK 标志位(除非您使用 --scanflags) 当扫描未被过滤的系统 时, open(开放的)和 closed(关闭的) 端口都会返回 RST 报文。Nmap 把它们标记为 unfiltered(未被过滤的),意思是 ACK 报文不能到达,但至于它们是 open(开放的)或者 closed(关闭的) 无法确定。不响应的端口或者发送特定的 ICMP 错误消息(类型 3,代号 1,2,3,9,10,或者 13)的端口,标记为 filtered(被过滤的)。

-sW (TCP 窗口扫描)

除了利用特定系统的实现细节来区分开放端口和关闭端口,当收到 RST 时不总是打印 unfiltered,窗口扫描和 ACK 扫描完全一样。它通过检查返回的 RST 报文的 TCP 窗口域 做到这一点。在某些系统上,开放端口用正数表示窗口大小(甚至对于 RST 报文) 而关闭 端口的窗口大小为 0。因此,当收到 RST 时,窗口扫描不总是把端口标记为 unfiltered 而是根据 TCP 窗口值是正数还是 0,分别把端口标记为 open 或者 closed

该扫描依赖于互联网上少数系统的实现细节,因此您不能永远相信它。不支持它的系统 会通常返回所有端口 closed。当然,一台机器没有开放端口也是有可能的。如果大部分 被扫描的端口是 closed,而一些常见的端口 (如 22, 25,53) 是 filtered,该系统 就非常可疑了。偶尔地,系统甚至会显示恰恰相反的行为。 如果您的扫描显示 1000 个 开放的端口和 3 个关闭的或者被过滤的端口,那么那 3 个很可能也是开放的端口。

-sM (TCP Maimon 扫描)

Maimon 扫描是用它的发现者 Uriel Maimon 命名的。他在 Phrack Magazine issue #49 (November 1996)中描述了这一技术。 Nmap 在两期后加入了这一技术。这项技术和 Null FIN,以及 Xmas 扫描完全一样,除了探测报文是 FIN/ACK。根据 RFC 793 (TCP),无论端 口开放或者关闭,都应该对这样的探测响应 RST 报文。然而,Uriel 注意到如果端口开放 许多基于 BSD 的系统只是丢弃该探测报文。

--scanflags (定制的 TCP 扫描)

真正的 Nmap 高级用户不需要被这些现成的扫描类型束缚 --scanflags 选项允许您通过 指定任意 TCP 标志位来设计您自己的扫描。让您的创造力流动,躲开那些仅靠本手册添 加规则的入侵检测系统!

--scanflags 选项可以是一个数字标记值如 9 (PSH 和 FIN),但使用字符名更容易些。只 要是 URG, ACK,PSH, RST,SYN,and FIN 的任何组合就行。例如,--scanflags URGACKPSHRSTSYNFIN 设置了所有标志位,但是这对扫描没有太大用处。标志位的顺序不 重要。

除了设置需要的标志位,您也可以设置 TCP 扫描类型(如-sA 或者-sF)。那个基本类型告 诉 Nmap 怎样解释响应。例如, SYN 扫描认为没有响应意味着 filtered 端口,而 FIN 扫 描则认为是 open|filtered。除了使用您指定的 TCP 标记位,Nmap 会和基本扫描类型一 样工作。如果您不指定基本类型,就使用 SYN 扫描。

-sI <zombie host[:probeport]> (Idlescan)

这种高级的扫描方法允许对目标进行真正的 TCP 端口盲扫描 (意味着没有报文从您的真 实 IP 地址发送到目标)。相反,side-channel 攻击 利用 zombie 主机上已知的 IP 分段 ID 序列生成算法来窥探目标上开放端口的信息。 IDS 系统将显示扫描来自您指定的 zombie 机(必须运行并且符合一定的标准)。 这种奇妙的扫描类型太复杂了,不能在此完 全描述,所以我写一篇非正式的论文, 发布在 http://nmap.org/book/idlescan.html

除了极端隐蔽(由于它不从真实 IP 地址发送任何报文), 该扫描类型可以建立机器间的 基于 IP 的信任关系。 端口列表从 zombie 主机的角度。显示开放的端口。 因此您可以 尝试用您认为(通过路由器/包过滤规则)可能被信任的 zombies 扫描目标。

如果您由于 IPID 改变希望探测 zombie 上的特定端口, 您可以在 zombie 主机后加上一 个冒号和端口号。 否则 Nmap 会使用默认端口(80)。

-sO (IP 协议扫描)

IP 协议扫描可以让您确定目标机支持哪些 IP 协议 (TCP,ICMP,IGMP,等等)。从技术 上说,这不是端口扫描,既然它遍历的是 IP 协议号而不是 TCP 或者 UDP 端口号。但是它 仍使用 -p 选项选择要扫描的协议号,用正常的端口表格式报告结果,甚至用和真正的端 口扫描一样的扫描引擎。因此它和端口扫描非常接近,也被放在这里讨论。

除了本身很有用,协议扫描还显示了开源软件的力量。尽管基本想法非常简单,我过去 从没想过增加这一功能也没收到任何对它的请求。在 2000 年夏天,Gerhard Rieger 孕育 了这个想法,写了一个很棒的补丁程序,发送到 nmap-hackers 邮件列表。我把那个补丁 加入了 Nmap,第二天发布了新版本。几乎没有商业软件会有用户有足够的热情设计并贡 献他们的改进。

协议扫描以和 UDP 扫描类似的方式工作。它不是在 UDP 报文的端口域上循环,而是在 IP 协议域的 8 位上循环,发送 IP 报文头。报文头通常是空的,不包含数据,甚至不包含所 申明的协议的正确报文头 TCP,UDP,和 ICMP 是三个例外。它们三个会使用正常的协议头,因为否则某些系统拒绝发送,而且 Nmap 有函数创建它们。协议扫描不是注意 ICMP 端口不可到达消息,而是 ICMP 协议不可到达消息。如果 Nmap 从目标主机收到任何协议 的任何响应,Nmap 就把那个协议标记为 open。 ICMP 协议不可到达错误(类型 3,代号 2) 导致协议被标记为 closed。其它 ICMP 不可到达协议(类型 3,代号 1,3,9,10,或者 13) 导致协议被标记为 filtered (虽然同时他们证明 ICMP 是 open )。如果重试之后仍 没有收到响应,该协议就被标记为 open|filtered

-b <ftp relay host> (FTP 弹跳扫描)

FTP 协议的一个有趣特征(RFC 959) 是支持所谓代理 ftp 连接。它允许用户连接到一台 FTP 服务器,然后要求文件送到一台第三方服务器。这个特性在很多层次上被滥用,所以 许多服务器已经停止支持它了。其中一种就是导致 FTP 服务器对其它主机端口扫描。只 要请求 FTP 服务器轮流发送一个文件到目标主机上的所感兴趣的端口。错误消息会描述 端口是开放还是关闭的。这是绕过防火墙的好方法,因为 FTP 服务器常常被置于可以访 问比 Web 主机更多其它内部主机的位置。 Nmap 用-b 选项支持 ftp 弹跳扫描。参数格式 是 username:password@server:port。 Server 是某个脆弱的 FTP 服务器的名字或者 IP 地址。您也许可以省略 username:password,如果服务器上开放了匿名用户 (user:anonymous password:-wwwuser@)。端口号(以及前面的冒号) 也可以省略,如果 server 使用默认的 FTP 端口(21)。

当 Nmap1997 年发布时,这个弱点被广泛利用,但现在大部分已经被 fix 了。脆弱的服务 器仍然存在,所以如果其它都失败了,这也值得一试。如果您的目标是绕过防火墙,扫 描目标网络上的开放的 21 端口(或者甚至任何 ftp 服务,如果您用版本探测扫描所有端 口),然后对每个尝试弹跳扫描。Nmap 会告诉您该主机脆弱与否。如果您只是试着玩 Nmap, 您不必(事实上,不应该)限制您自己。在您随机地在互联网上寻找脆弱的 FTP 服务器时 考虑一下系统管理员不太喜欢您这样滥用他们的服务器。