NMAP 使用小技巧
IDS 绕过 + 效率提升
简介
仅仅是引论。
介绍 nmap 的工作流程、重点关注端口扫描技术。
介绍 nmap 提供扫描技术,以及适用场景。
介绍 nmap 速度调整选项。
介绍两个常见的 IDS 检测机制。以及如何绕过。
关于 nmap
工作流程
Script pre-scanning.
Target enumeration. -sL -n 分析用户给出的目标。
Host discovery (ping scanning). 主机发现,用来避免对离线的主机进行接下来的扫描。
Reverse-DNS resolution.
Port scanning. 端口扫描,-sn 跳过这步
Version detection. 检测 open 状态端口的服务。
OS detection.
Traceroute.
Script scanning.
Output.
Script post-scanning.
端口扫描技术
这里只简单介绍原理和适用场景,详情请参照:https://nmap.org/book/scan-methods.html
-
-sS:SYN 扫描
-
-sF、-sN、-sX
用来判断端口是否开放,但有可能无法建立连接。通常适用于低版本 unix。
原理是两个特性:
- 利用了 RFC 793 里的一个细节,windows 不遵守。
- 如果一个端口关闭,非 RST 的请求以 RST 响应。
- 如果一个端口开放,非 SYN | RST | ACK 的请求,都忽略。
- 当无状态防火墙被配置不允许外部主动发起连接(拒绝SYN),但可以主动向外发起连接(接收 SYNACK )
- 利用了 RFC 793 里的一个细节,windows 不遵守。
-
-sA:
不能用来确定端口是否开放,用来确定是否有防火墙,并且是否是基于状态的防火墙。原理:
- 没有防火墙,或基于规则防火墙。因为接收到非预期 ACK ,不管端口开放与否,都会响应 RST 。
- 基于状态防火墙:检测没有主动发起连接,所以直接丢弃这个包,无响应。
-
-sT:能用 -sT ,就能用 -sS。
-
-sI:属于旁信道探测。需要支持源地址欺骗,并且有一个网络状态空闲的僵尸机。条件较为苛刻,并且没有带来过多好处。附加一张图。
-
-b
需要有一个支持代理的 ftp 服务器访问权限,让这个ftp 服务器向其它主机的端口发送文件,根据响应判断端口是否开放。
-
-sW:
-sW 和 -sA 行为一样,不过会进一步检查 RST 响应的窗口值,来判断端口是否开放。但不准(测试了win、linux)。官方文档说少数系统有用。
-
-sM:
原理是 1996 BSD 的系统的小特性。现在都被修复了。
IDS 的绕过
IDS 如何检测 nmap 的扫描行为
常见的有两种:
-
根据 nmap 的流量特征字段 (IDS 规则)
window size、payload size
-
端口访问行为。(sfportscan )
一段时间内访问有效的端口与访问无效端口之间 的数学统计。
配置 ids
snort 是一个开源 IDS/IPS 软件。https://www.snort.org/
对于检测端口扫描来说,其既支持通过 IDS 规则匹配流量特征、也支持通过 sfportscan 插件来对端口访问行为进行统计检测。
https://rules.emergingthreats.net/OPEN_download_instructions.html 开源 IDS 规则集。在其中下载适用于 snort 的规则集、在规则文件 emerging-scan.rules 中,关于 nmap ,有24 项规则,有端口扫描、服务探测、系统探测等检测方面。
所以,想要绕过这个规则,只需要使以上任一条规则为假即可。
IDS 规则以及绕过
-sS
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sS window 1024"; fragbits:!D; dsize:0; flags:S,12; ack:0; window:1024; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2009582; classtype:attempted-recon; sid:2009582; rev:3; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sS window 2048"; fragbits:!D; dsize:0; flags:S,12; ack:0; window:2048; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000537; classtype:attempted-recon; sid:2000537; rev:8; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sS window 3072"; fragbits:!D; dsize:0; flags:S,12; ack:0; window:3072; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2009583; classtype:attempted-recon; sid:2009583; rev:3; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sS window 4096"; fragbits:!D; dsize:0; flags:S,12; ack:0; window:4096; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2009584; classtype:attempted-recon; sid:2009584; rev:2; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
-
fragbits:!D;
当 IP flags 字段 Don`t Fragment 比特位为 0 时,此条件为真。通过观察上网过程中数据包,发现有 0 有 1 ,所以这条可以不用管。
-
dsize:0
表示传输层 payload 大小为 0 。携带的数据大小,nmap 提供
--data-length num
选项可以指定附加 num 个字节的随机数据。但通常 SYN 数据包默认不携带载荷,即为 0。
-
flags:S,12
TCP flags 位,S 为 SYN 并且忽略 cwr(1)、ece(2)(这条语句匹配的是flags 中除这两个bit位,其它bit 位只有 syn 置位)。实际数据包相似,不用更改。
-
ack:0
表示 TCP ack number 为 0 。实际握手数据包相似,不需要更改。
-
window:1024
TCP window size 为 1024 。在 tcpip.cc 665 行中,将其修改为
tcp->th_win = htons(12573+get_random_u8());
-sC
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"ET SCAN Nmap Scripting Engine User-Agent Detected (Nmap NSE)"; flow:to_server,established; content:"User-Agent|3a| Nmap NSE"; http_header; reference:url,doc.emergingthreats.net/2009359; classtype:web-application-attack; sid:2009359; rev:4; metadata:created_at 2010_07_30, updated_at 2020_05_04;)
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"ET SCAN Nmap Scripting Engine User-Agent Detected (Nmap Scripting Engine)"; flow:to_server,established; content:"User-Agent|3a| Mozilla/5.0 (compatible|3b| Nmap Scripting Engine"; fast_pattern:38,20; http_header; nocase; reference:url,doc.emergingthreats.net/2009358; classtype:web-application-attack; sid:2009358; rev:5; metadata:created_at 2010_07_30, updated_at 2020_04_22;)
alert tcp $HOME_NET any -> any any (msg:"ET SCAN Possible Nmap User-Agent Observed"; flow:to_server,established; content:"User-Agent|3a|"; http_header; content:"|20|Nmap"; http_header; fast_pattern; distance:0; classtype:web-application-attack; sid:2024364; rev:3; metadata:affected_product Any, attack_target Client_and_Server, created_at 2017_06_08, deployment Perimeter, former_category SCAN, performance_impact Low, signature_severity Informational, updated_at 2020_08_06;)
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"ET SCAN NMAP SQL Spider Scan"; flow:established,to_server; content:"GET"; http_method; content:" OR sqlspider"; http_uri; reference:url,nmap.org/nsedoc/scripts/sql-injection.html; classtype:web-application-attack; sid:2013778; rev:1; metadata:created_at 2011_10_19, updated_at 2020_04_20;)
-
flow:to_server,established;
当收到客户端请求时,并且是已建立 tcp 连接的请求。 -
content:"User-Agent|3a| Nmap NSE";
content 表示在传输层 payload 中搜索。content 后直接跟的是一些修饰词。对搜索做进一步限制。
http_header;
、http_method;
、http_uri;
限制其在 http 中不同部位进行搜索。fast_pattern:38,20;
用于性能优化的修饰词,跟主题关系不大。distance:0;
用来指出上一个 content 结束后间隔多少个字节再匹配此 content 。nocase;
忽略大小写
nselib/http.lua 159 行,修改即可。
Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36
-sV
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -f -sV"; fragbits:!M; dsize:0; flags:S,12; ack:0; window:2048; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000545; classtype:attempted-recon; sid:2000545; rev:8; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
-O
alert udp $EXTERNAL_NET 10000: -> $HOME_NET 10000: (msg:"ET SCAN NMAP OS Detection Probe"; dsize:300; content:"CCCCCCCCCCCCCCCCCCCC"; fast_pattern:only; content:"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"; depth:255; content:"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"; within:45; classtype:attempted-recon; sid:2018489; rev:3; metadata:created_at 2014_05_20, updated_at 2019_10_07;)
-
content 修饰词
depth:255;
指的是在 tcp payload 最多查看前 255 个字节。within:45;
表示在前一个 content 末尾 45 个字节内搜索此content
在 osscan2.cc 2149 行中
将其更改为其它字节
static u8 patternbyte = 0x45; /* character 'E' */
-sA
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sA (1)"; fragbits:!D; dsize:0; flags:A,12; window:1024; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000538; classtype:attempted-recon; sid:2000538; rev:8; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -sA (2)"; fragbits:!D; dsize:0; flags:A,12; window:3072; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000540; classtype:attempted-recon; sid:2000540; rev:8; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
绕过以上,就足以绕过这些
-sF -sN -sX -sM
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -f -sF"; fragbits:!M; dsize:0; flags:F,12; ack:0; window:2048; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000543; classtype:attempted-recon; sid:2000543; rev:7; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -f -sN"; fragbits:!M; dsize:0; flags:0,12; ack:0; window:2048; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000544; classtype:attempted-recon; sid:2000544; rev:7; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"ET SCAN NMAP -f -sX"; fragbits:!M; dsize:0; flags:FPU,12; ack:0; window:2048; threshold: type both, track by_dst, count 1, seconds 60; reference:url,doc.emergingthreats.net/2000546; classtype:attempted-recon; sid:2000546; rev:7; metadata:created_at 2010_07_30, updated_at 2010_07_30;)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"GPL SCAN nmap XMAS"; flow:stateless; flags:FPU,12; reference:arachnids,30; classtype:attempted-recon; sid:2101228; rev:8; metadata:created_at 2010_09_23, updated_at 2010_09_23;)
绕过以上,就足以绕过这些
基于统计的 ids 绕过
- 挂代理
- 调整扫描速度
内网环境下源地址伪造
此外,还有些技术是基于内网环境端口扫描,例如以下。
- -S / -g 伪造源 ip / 源端口 -D 伪造多个源地址。不过试了一下,伪造失败,推测网关路由器过滤不合法符的源 ip。可能对于交换机环境有用。
- -sI 基于源地址伪造的扫描技术。
时间与效率
nmap 提供的控制选项
可以参照来微调,
-
min-rtt-timeout max-rtt-timeout initial-rtt-timeout
指定一个探测请求的 timeout 。通常来讲,可以通过来判断 ping 目标的时间来设置。
-
max-retries
很值得设置如果确定整个通信过程比较稳定,那就设置为 0
测试结果
耗时:149,110,120,132,130,116,152,139
耗时:65,62,59,59,64,60,63,60
扫描结果是相同的。如果说网络比较稳定,目标比较边缘,不在意隐蔽性,那么就可以尝试。
虽然一个目标可能差距不大,但数量一多,效率还是比较可观。
其它
在虚拟机上扫的结果与主机上结果不同。用 wireshark 抓包后发现,在扫描结果出来后,7777 响应包才到,意味着响应时间超过 rtt 。
为排除其它软件的影响,重启后也一样。
虚拟机使用的是 NAT ,vmware NAT 的处理也是要耗时的。对时间较为敏感的操作,尽量不要在 NAT 模式的虚拟机上做。桥接模式也类似,主机更稳定点。
总结
网上公开的资料不多,也受限于实验环境,作为引论,欢迎小伙伴们一起交流。
-
针对端口扫描技术
- 首选 -sS ,尽量不要用 -sT
- -sN、-sF、-sX:三个是相似的,用来判断端口是否开放,但有可能无法建立连接。通常适用于低版本 unix。
- -sA :用来判断对方是否为有无状态的防火墙。对于阿里云之类的云主机,可能是有防护。
- -sI、-b :通常只有在内网环境才能达成使用条件。
- -sM、-sW:完全不行了。
- -sU :使用较少。。
-
尽可能修改 nmap 的特征值,以绕过 ids 防护规则。
-
在网络稳定的情况下。可以使用
--max-retries 0
以降低重传的次数。对效率提升巨大。 -
根据目标判断,如无特别必要,尽量不要扫全端口。百度、淘宝首页之类服务器,基本不会开放其它端口。但像小型公司,或者边缘业务,或者内网环境,就可以试试。
使用
--top-ports 4000
已经可以覆盖 99% 常见端口。 -
追求隐秘性:
- 修改 nmap 特征。
- 特殊情况下,可以使用
--data-length <len>
来携带一定数量的载荷。 - 限制每秒发包的速率
--max-rate <num>
或者使用-T0 -T1
等时间模板的控制。 - 使用 socks 代理。
- 将要扫描的端口分段,在不同的时间段扫描。
-p
- 在内网环境下,可以进一步使用
-S -D --spoof-mac
等伪造来源的技术。