前 18 篇文章完成了模块 0 的全部基础筑基——从 Linux 系统操作到网络协议、从密码学原理到编程基础、从 Docker 容器到安全靶场部署。现在站在这个基础上,我们要做一个视角翻转:不再只看"怎么防御",而是开始研究"怎么攻击"。这不是鼓励破坏,而是渗透测试的核心逻辑——只有像攻击者一样思考,才能发现真正有价值的漏洞。
MITRE ATT&CK 框架是这套攻击方法论的导航系统。它把真实世界中观察到的攻击行为分为 14 个战术(Tactic),每个战术下包含多个技术(Technique)。我们在学习每个攻击工具和技术时,都会标注对应的 ATT&CK 编号,帮助你建立"攻击者按什么顺序做什么事"的框架性认知。
上图是 Lockheed Martin 网络杀伤链(Cyber Kill Chain)的简化版。侦察(Reconnaissance)是整条链的第一环——攻击者在发起任何实质性攻击之前,必须先搞清楚目标网络里有哪些活着的主机、开放了哪些端口、运行了什么服务。nmap 就是这一环节最经典的工具,对应 ATT&CK 框架中的 T1595 Active Scanning。
需要区分两个概念:主动侦察和被动侦察。主动侦察会向目标发送数据包(如 nmap 扫描),目标可能察觉;被动侦察不直接接触目标(如搜索公开信息、查询 DNS 记录),目标无感知。本篇聚焦主动扫描中的 nmap,下一篇会覆盖被动侦察工具。
nmap(Network Mapper)由 Gordon "Fyodor" Lyon 于 1997 年发布,至今仍是网络安全领域使用率最高的扫描工具。2026 年 3 月 26 日发布的 7.99 版本带来了多项改进:支持通过 VPN 接口(如 OpenVPN TAP)扫描、NSE 脚本 http-internal-ip-disclosure 新增 IPv6 和 HTTPS 支持、修复了反向 DNS 查询速度退化问题,并更新了 libpcap 1.10.6、PCRE2 10.47 等底层库。
Kali Linux 默认预装 nmap。在其他 Debian/Ubuntu 系统上手动安装:
macOS 上可用 Homebrew 安装:brew install nmap。但 macOS 和 Linux 版本的 SYN 扫描需要 root 权限,因为要构造原始 TCP 数据包。
理解 nmap 的核心在于理解 TCP/IP 协议栈的工作方式。模块 0-2 中学过 TCP 三次握手:客户端发 SYN,服务端回 SYN-ACK,客户端再回 ACK。nmap 的各种扫描类型本质上就是利用 TCP/UDP/ICMP 协议的各种标志位组合,观察目标的响应来推断端口状态。
| 扫描阶段 | 核心问题 | 对应 nmap 功能 |
|---|---|---|
| 主机发现 | 哪些 IP 的主机是开机的、在线的? | -sn / -Pn |
| 端口扫描 | 哪些端口是开放的、可连接的? | -sS / -sT |
| 版本探测 | 开放端口上运行的是什么服务、什么版本? | -sV |
| 系统识别 | 目标主机运行什么操作系统? | -O |
| 漏洞检测 | 服务是否存在已知漏洞? | --script |
nmap 命令的基本结构:nmap [扫描类型] [选项] [目标]。目标可以是单个 IP、CIDR 网段、域名或 IP 范围。
输出格式有三种常用形式。标准输出直接打印到终端;XML 输出(-oX)方便程序解析,可导入其他工具;Grep 输出(-oG)便于在命令行中用 grep 过滤。
-oA 同时生成三种格式:XML 供工具导入、TXT 供人工阅读、Grep 供快速过滤。然后用 xsltproc scan_result.xml -o report.html 可将 XML 转为美观的 HTML 报告。扫描一个网段时,第一步不是直接扫端口——那样太慢且容易被发现。应该先用主机发现技术快速判断哪些 IP 上有活着的主机,然后只对在线主机做端口扫描。nmap 默认在进行端口扫描前会先执行主机发现。
nmap 对局域网和广域网采用不同的默认主机发现策略。扫描同一局域网(nmap 通过路由表判断)时,默认使用 ARP 请求——发一个 ARP 包,收到回应说明主机在线,速度极快且无法被防火墙阻止。扫描广域网时,默认发送 TCP SYN 到 80 和 443 端口、ICMP Echo 请求和 ICMP Timestamp 请求。
加 -sn 后 nmap 只做主机发现,不进行端口扫描。适合快速摸清整个网段的在线设备清单。
注意上面第一行的 sudo——在局域网中 nmap 用 ARP 做主机发现,构造 ARP 请求需要 root 权限。不加 sudo 时退化为使用 TCP/ICMP 探测,可能遗漏部分主机。
有些主机配置了防火墙丢弃所有 ICMP 包,nmap 会误判为离线。加 -Pn 跳过主机发现步骤,直接对每个目标 IP 执行端口扫描。代价是扫描时间变长,因为要对每个"可能在线"的 IP 都做端口探测。
nmap 允许精确控制主机发现使用的探测包类型。这在目标防火墙仅放行特定协议时非常有用:
| 选项 | 探测类型 | 说明 |
|---|---|---|
-PS22,80,443 |
TCP SYN Ping | 向指定端口发 SYN 包,收到 SYN-ACK 或 RST 表示主机在线 |
-PA80,443 |
TCP ACK Ping | 发 ACK 包,收到 RST 表示在线(绕过只拦 SYN 的防火墙) |
-PE |
ICMP Echo | 传统 Ping 请求,许多防火墙会丢弃 |
-PP |
ICMP Timestamp | 时间戳请求,有时能绕过 Echo 过滤 |
-PR |
ARP Ping | 局域网最可靠的方式,无法被软件防火墙阻止 |
sudo nmap -sn 192.168.1.0/24 — 局域网扫描必须加 sudo 才能用 ARP 探测
主机发现找到在线目标后,下一步是端口扫描——判断哪些端口处于开放状态。端口扫描是 nmap 的核心能力,也是渗透测试中最频繁使用的功能。理解不同扫描类型的原理,才能在不同网络环境下选择最合适的方案。
nmap 将端口分为六种状态,理解每种状态的含义是分析扫描结果的基础:
SYN 扫描是 nmap 默认且最推荐的扫描方式。它只完成 TCP 三次握手的前两步——发送 SYN 包,收到 SYN-ACK 表示端口开放,收到 RST 表示端口关闭,然后立即发 RST 断开连接,不完成第三次握手。因为连接没有真正建立,服务器端的日志几乎不会记录这次扫描,所以也叫"半开扫描"。
SYN 扫描需要 root 权限,因为要构造原始 TCP 数据包(使用 raw socket),普通用户无法操作。
当没有 root 权限时,SYN 扫描无法使用,退而求其次选 -sT。它完成完整的 TCP 三次握手:发 SYN → 收到 SYN-ACK → 回 ACK 建立连接 → 立即断开。因为连接真正建立了,服务器日志会记录这次访问,隐蔽性差。但由于使用操作系统标准 socket API,不需要 root 权限。
UDP 扫描检测 UDP 端口状态。由于 UDP 是无连接协议,没有 SYN-ACK 这样的握手过程,nmap 发送空的 UDP 包到目标端口,然后根据回应判断:收到 UDP 回应表示端口 open;收到 ICMP Port Unreachable 表示端口 closed;收到 ICMP 其他类型错误表示 filtered;无回应表示 open|filtered。
UDP 扫描非常慢,因为必须等待超时(防火墙可能丢包而非返回 ICMP 错误)。实际使用中通常只扫描关键 UDP 端口:
ACK 扫描发送仅设置 ACK 标志的 TCP 包。根据 RFC 793,端口开放或关闭时都应回应 RST,所以 ACK 扫描不能判断端口是否开放——但能判断端口是否被防火墙过滤。收到 RST 表示 unfiltered(未过滤),无回应表示 filtered(被过滤)。这在绘制网络拓扑、判断防火墙规则时非常有用。
-p- 在实际渗透测试中非常必要。很多管理员会把服务搬到非标准端口(如把 SSH 从 22 搬到 22222),以为这样能增加安全性。但攻击者扫描全端口后照样能发现。隐藏端口不是安全策略,只是增加了一点扫描时间。知道端口开放只是第一步。端口 80 可能运行 Nginx,也可能运行 Apache、IIS 或者一个用 Go 写的自定义 HTTP 服务——不同软件和版本对应的漏洞完全不同。版本探测和操作系统识别就是回答"端口上跑的是什么"和"这台机器是什么系统"这两个问题。
-sV 通过向开放端口发送一系列探测数据包(nmap-service-probes 库中定义了数百种探测规则),分析返回的 Banner 和行为特征来判断服务类型和版本。它的工作过程像一个自动化的"试错对话":先发 HTTP 请求看回应,不对就发 SSL 握手,再不对就发 DNS 查询……直到匹配出服务。
VERSION 列显示了具体的服务名和版本号。拿到这些信息后,下一步通常是搜索该版本对应的已知漏洞。比如 OpenSSH 9.6p1 可能有一个 CVE 编号的漏洞,MySQL 8.0.42 可能有另一个——这就是版本探测在攻击链中的价值。
版本探测的深度可调。nmap 为每个探测规则分配了 1-9 的稀有度等级(rarity),等级越高越少用但更特殊。--version-intensity 设置只使用 rarity 不超过该值的探测规则。默认值 7,范围 0-9。提高强度能识别更多服务但更慢:
-O 通过分析 TCP/IP 协议栈实现的差异来推断操作系统类型。不同操作系统对 TCP 选项、ICMP 响应、IP 包头的处理方式有微妙差异——Linux 的 TTL 默认 64,Windows 的 TTL 默认 128,macOS 的 TCP 选项排列方式与两者都不同。nmap 维护了一个包含数千种 OS 指纹的数据库(nmap-os-db),通过比对来判断。
-A 是"一站式"选项,等同于同时启用 -sV + -O + --traceroute + --script=default。适合对单个目标做快速全面的侦察,但扫描时间较长。
-sV)比 OS 识别(-O)更可靠。Nmap Scripting Engine(NSE)是 nmap 最强大的扩展能力。它内置超过 600 个 Lua 脚本,覆盖漏洞检测、暴力破解、网络发现、后门检测等多个领域。7.99 版本对 NSE 做了多项改进,包括 http-internal-ip-disclosure 脚本新增 IPv6 和 HTTPS 支持、修复了 ms-sql 脚本的潜在崩溃问题、新增 NATS 服务器版本检测等。
NSE 脚本按功能分为多个类别,用 --script 参数指定:
| 类别 | 用途 | 常用脚本示例 |
|---|---|---|
default |
安全、快速的基础检查 | http-title、ssh-hostkey |
vuln |
已知漏洞检测 | http-vuln-cve2021-44228(Log4Shell) |
brute |
暴力破解 | ssh-brute、ftp-brute、mysql-brute |
auth |
认证绕过检测 | ftp-anon(匿名登录检测) |
discovery |
网络信息发现 | smb-os-discovery、dns-brute |
safe |
无害脚本(不影响目标) | 适用于生产环境扫描 |
用 vuln 类别脚本对目标进行漏洞扫描,是 NSE 最常用的场景之一。以下命令对目标 Web 服务运行所有漏洞检测脚本:
在 Windows 环境的渗透测试中,SMB 协议是信息收集的重点。nmap 的 SMB 系列脚本可以枚举共享、检测漏洞、获取系统信息:
nmap -sV --script=vuln -p 80,443,22,3306 192.168.1.100 — 先用 -sV 探测服务版本,再针对开放端口跑漏洞脚本
ls /usr/share/nmap/scripts/。查看脚本用法:nmap --script-help ssh-brute。更新脚本库:sudo nmap --script-updatedb,建议每次使用前更新以获取最新的漏洞检测规则。在实际渗透测试中,扫描速度和隐蔽性是一对矛盾——扫得越快越容易被 IDS/IPS 发现,扫得越慢越安全但客户等不了三天。nmap 提供了丰富的参数来平衡这两个需求。
nmap 预设了 6 个时序模板,从偏执到疯狂,控制发包间隔和并发数:
| 模板 | 名称 | 特点 | 适用场景 |
|---|---|---|---|
-T0 |
Paranoid | 串行发包,间隔 5 分钟 | 绕过老旧 IDS |
-T1 |
Sneaky | 串行发包,间隔 15 秒 | 谨慎扫描 |
-T2 |
Polite | 串行发包,不占带宽 | 生产环境扫描 |
-T3 |
Normal | 默认值,并行发包 | 通用场景 |
-T4 |
Aggressive | 高速并行,10 秒超时 | 局域网快速扫描 |
-T5 |
Insane | 极速扫描,可能丢包 | CTF 竞赛环境 |
日常使用中最常用 -T4——在局域网中既快又准。广域网扫描建议 -T3。需要隐蔽时用 -T1 或 -T2。-T5 不推荐用于正式渗透测试,因为丢包会导致误判端口状态。
诱饵扫描让目标以为有多个 IP 同时在扫描,无法确定哪个是真正的攻击者。nmap 会伪造多个源 IP 的探测包与真实探测包混合发送:
RND:5 让 nmap 随机生成 5 个诱饵 IP。ME 表示你自己的真实 IP 在诱饵列表中的位置,放在中间时迷惑性最强。注意诱饵 IP 必须是"活着"的(能响应 SYN-ACK),否则防火墙可能直接过滤掉那些"死诱饵"的包,反而暴露了你的真实 IP。
-f 把 TCP 头拆分成多个小 IP 包发送,部分防火墙只检查第一个分片而放行后续分片,从而绕过检测。但现代防火墙通常都会重组分片后再检查,所以这个技巧在 2026 年的实际效果有限。更实用的规避方法是降低扫描速度(-T1 或 --scan-delay 1s),让流量混入正常通信中。把前面学到的技术串联成一个完整的渗透测试侦察流程。场景设定:在云服务器上部署了 DVWA 靶场(192.168.1.100),从树莓派上远程执行完整攻击面评估。
这个流程从宏观到微观,先发现主机,再扫描全端口,接着探测版本和系统,最后针对性漏洞检测。每一步的结果指导下一步的操作——发现 80 端口开放才知道要跑 Web 相关的漏洞脚本,发现 445 端口开放才知道要跑 SMB 脚本。这就是渗透测试侦察阶段的标准方法论。
nmap -sS -sV -p 80,443 靶机IP 扫描它。记录输出的 VERSION 列,确认 DVWA 运行在什么 Web 服务上、版本号是多少。-oA 生成扫描报告,然后尝试:1)用 grep 从 .gnmap 文件中提取所有 open 端口;2)用 xsltproc 将 XML 转为 HTML 报告并在浏览器中查看。--script=vuln 执行漏洞扫描,找到一个报告的漏洞后:1)搜索该 CVE 编号的详细信息;2)尝试理解该漏洞的利用条件;3)思考——如果这是一个真实服务器,你会建议管理员采取什么修复措施?提示:可以关注 Nginx 版本漏洞或 SSH 配置弱口令。