From 3d382bdf17530bd20d04d43e4444883b5970cc61 Mon Sep 17 00:00:00 2001 From: dmiller Date: Mon, 31 Aug 2020 15:20:49 +0000 Subject: [PATCH] New option --discovery-ignore-rst. Closes #1616 --- CHANGELOG | 4 ++++ NmapOps.cc | 1 + NmapOps.h | 1 + docs/refguide.xml | 17 +++++++++++++++++ nmap.cc | 3 +++ scan_engine_connect.cc | 4 +++- scan_engine_raw.cc | 10 +++++++--- 7 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 391182e75..36936129b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#1616] New option --discovery-ignore-rst tells Nmap to ignore TCP RST + responses when determining if a target is up. Useful when firewalls are + spoofing RST packets. [Tom Sellers] + o [Ncat][GH#2087][GH#1927][GH#1928][GH#1974] It is now possible to override the value of TLS SNI via --ssl-servername [Hank Leininger, nnposter] diff --git a/NmapOps.cc b/NmapOps.cc index 341420e08..284f87a30 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -398,6 +398,7 @@ void NmapOps::Initialize() { exclude_portlist = NULL; proxy_chain = NULL; resuming = false; + discovery_ignore_rst = false; } bool NmapOps::SCTPScan() { diff --git a/NmapOps.h b/NmapOps.h index a3738cd9f..4d0977554 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -396,6 +396,7 @@ class NmapOps { char *exclude_portlist; /* exclude-ports list specified by user */ nsock_proxychain proxy_chain; + bool discovery_ignore_rst; /* host discovery should not consider TCP RST packet responses as a live asset */ #ifndef NOLUA bool script; diff --git a/docs/refguide.xml b/docs/refguide.xml index 83351639d..8cd8ffce6 100644 --- a/docs/refguide.xml +++ b/docs/refguide.xml @@ -871,6 +871,23 @@ content can also be affected with the , + + + + + + + + In some cases, firewalls may spoof TCP reset (RST) replies in + response to probes to unoccupied or disallowed addresses. Since + Nmap ordinarily considers RST replies to be proof that the target + is up, this can lead to wasted time scanning targets that aren't + there. Using the will + prevent Nmap from considering these replies during host discovery. + You may need to select extra host discovery options to ensure you + don't miss targets in this case. + + diff --git a/nmap.cc b/nmap.cc index e056c8541..e3472b7cd 100644 --- a/nmap.cc +++ b/nmap.cc @@ -627,6 +627,7 @@ void parse_options(int argc, char **argv) { {"nsock-engine", required_argument, 0, 0}, {"proxies", required_argument, 0, 0}, {"proxy", required_argument, 0, 0}, + {"discovery-ignore-rst", no_argument, 0, 0}, {"osscan-limit", no_argument, 0, 0}, /* skip OSScan if no open ports */ {"osscan-guess", no_argument, 0, 0}, /* More guessing flexibility */ {"fuzzy", no_argument, 0, 0}, /* Alias for osscan_guess */ @@ -846,6 +847,8 @@ void parse_options(int argc, char **argv) { } else if ((strcmp(long_options[option_index].name, "proxies") == 0) || (strcmp(long_options[option_index].name, "proxy") == 0)) { if (nsock_proxychain_new(optarg, &o.proxy_chain, NULL) < 0) fatal("Invalid proxy chain specification"); + } else if (strcmp(long_options[option_index].name, "discovery-ignore-rst") == 0) { + o.discovery_ignore_rst = true; } else if (strcmp(long_options[option_index].name, "osscan-limit") == 0) { o.osscan_limit = true; } else if (strcmp(long_options[option_index].name, "osscan-guess") == 0 diff --git a/scan_engine_connect.cc b/scan_engine_connect.cc index b52292a96..662b01f93 100644 --- a/scan_engine_connect.cc +++ b/scan_engine_connect.cc @@ -272,7 +272,9 @@ static void handleConnectResult(UltraScanInfo *USI, HostScanStats *hss, /* This can happen on localhost, successful/failing connection immediately in non-blocking mode. */ case ECONNREFUSED: - newhoststate = HOST_UP; + if (!o.discovery_ignore_rst) { + newhoststate = HOST_UP; + } newportstate = PORT_CLOSED; current_reason = ER_CONREFUSED; break; diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index 2464868c0..f74974698 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -777,9 +777,13 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) { } else if (hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) { struct tcp_hdr *tcp = (struct tcp_hdr *) data; /* Check that the packet has useful flags. */ - if (!(tcp->th_flags & TH_RST) - && ((tcp->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK))) - continue; + if (o.discovery_ignore_rst + && (tcp->th_flags & TH_RST)) + continue; + else if (!(tcp->th_flags & TH_RST) + && ((tcp->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK))) + continue; + /* Now ensure this host is even in the incomplete list */ hss = USI->findHost(&hdr.src); if (!hss)