Security

Supercharge Nmap: Advanced Penetration Testing with Firewall Evasion, Dirbusting, DoS Simulation, and More

Nmap is the gold standard among port scanners and one of a pentester’s most important tools. But can you say you’ve truly mastered all its features and use cases? In this article, you’ll learn how to use Nmap to scan hosts behind a firewall, boost scan performance, identify holes in HTTP server configurations, stage a DoS attack, and even spin up a web server.

warning

All information is provided for informational purposes only. Neither the editorial team nor the author is responsible for any potential harm caused by the materials in this article.

Basic usage

Before we dive into Nmap’s advanced features, let’s spend a moment on the basics. You might argue there’s not much to it—just point Nmap at the target host, and after a short while it will print the open ports on screen:

$ nmap 192.168.0.1

That’s true, but keep in mind two specifics of how Nmap is implemented. First: when run without elevated privileges, Nmap is extremely inefficient. The scan effectively devolves into attempting a full connection to every port. For TCP, that means Nmap sends a SYN; if the target port is open, the host replies with SYN/ACK, Nmap responds with ACK, and only then closes the connection with a FIN.

The entire process uses the connect() system call and runs entirely through the OS networking stack. As a result, both scanning performance and stealth suffer—services listening on the scanned ports will actively log these connection attempts.

Nmap behaves quite differently when run with root privileges:

$ sudo nmap 192.168.0.1

In this mode, Nmap fully handles packet crafting and connection control itself. Connecting to open ports works like this: Nmap sends a SYN, the host replies with SYN/ACK, and Nmap responds with an RST, aborting the half-open handshake (this is the TCP SYN scan). As a result, the service listening on the port typically doesn’t log a connection attempt, and Nmap can detect a firewall that simply drops SYN packets instead of replying with SYN/ACK (open) or RST (closed), as a normal TCP/IP stack would. This scanning method is also significantly more efficient and faster.

The second thing to know about Nmap is that it doesn’t actually scan the entire port range (65,536); by default it only scans 1,000 common service ports defined in the /usr/share/nmap/nmap-services file. So if someone runs a service on a nonstandard port that isn’t listed in that file, Nmap won’t see it. You can change this behavior with a command like this:

$ sudo nmap -sS -sU -p 1-65535 192.168.0.1

Nmap will use a TCP SYN scan and a UDP scan across the entire port range.

Identifying the service and version running on a port

One of Nmap’s neat features is that it can not only determine a port’s state (open, closed, filtered) but also identify the daemon/service running on that port—and in some cases even its version. To do this, Nmap can use several techniques, such as connecting to port 80 and sending an HTTP request to learn the web server’s name and version, or analyzing how a service responds to specific packets and probes.

All the rules for identifying services and their versions are defined in the file /usr/share/nmap/nmap-service-probes, and the -sV flag tells Nmap to apply them:

$ sudo nmap -sV 192.168.0.1

You can even make Nmap try harder to identify the service by using the --version-all flag:

$ sudo nmap -sV --version-all 192.168.0.1

However, this usually doesn’t improve recognition accuracy.

Nmap couldn’t determine the HTTP server version, but it identified the server name
Nmap couldn’t determine the HTTP server version, but it identified the server name

Detecting the OS and version

This is probably one of Nmap’s most famous features. By sending nonstandard packets and comparing the target’s responses (response time, TTL, MTU, ACK values, and more) against its OS fingerprint database (/usr/share/nmap/nmap-os-db), Nmap can quite accurately determine the operating system running on the host. All you need to do is run Nmap with the -O flag:

$ sudo nmap -O 192.168.0.1

However, Nmap can’t always identify the operating system with 100% accuracy. If it can’t, it will list the closest matches and include a confidence percentage for each—90%, 82%, and so on.

Moreover, you can go even further and use the -A flag to have Nmap attempt OS detection, identify service versions, and even perform more in-depth service analysis using NSE scripts (more on those later):

$ sudo nmap -A 192.168.0.1
Nmap’s OS version guesses for the scanned host
Nmap’s OS version guesses for the scanned host

Speeding Up Your Scans

Nmap is known for its phenomenal performance, which has been improving for over two decades. The scanner uses a host of techniques and tricks, a multithreaded mode with a dynamically adjusted number of ports per thread, and it can leverage multiple CPU cores. Yet even with a truckload of optimizations in its code, Nmap isn’t as fast by default as it could be.

Nmap supports roughly a dozen flags that let you fine-tune parameters like the delay between port connection attempts or the number of retries. Getting a handle on all of them at once can be tough, so Nmap provides a set of predefined timing (aggressiveness) templates. There are six of these (0 through 5), and you can select one with the -T option:

$ sudo nmap -T3 192.168.0.1

In this case we chose timing template 3—the default—which balances scan speed and accuracy on slower networks. However, given that wired connections today typically exceed 30 Mbps, -T4 or even -T5 is often the better choice. Use the latter only on stable networks without bandwidth drops.

Lower timing templates are meant to evade intrusion detection systems. For example, -T0 disables multithreaded scanning and inserts a five‑minute delay between port probes; if you’re willing to spend a day (or night) scanning, there’s a chance the attempt won’t be noticed (especially since Nmap randomizes the port order). The -T1 template is faster with a 15‑second delay, -T2 uses 0.4 seconds, -T3 10 ms, and -T4 5 ms.

The -T5 mode is about 1.5× faster than the default
The -T5 mode is about 1.5× faster than the default

Covering Your Tracks

Increasing the delay between port probes isn’t the only way to hide that a host is being scanned. Another approach is to launch multiple scanning threads at once, spoofing the source IP in all but one case. The idea is to confuse the IDS and the host’s administrator. The IDS logs will show several scan attempts from different addresses, with only one of them being genuine.

Using this method is fairly straightforward:

$ sudo nmap -D address1,address2,address3 192.168.0.1

You can specify as many decoy addresses as you want, or have Nmap generate random ones for you (ten in this example):

$ sudo nmap -D RND:10 192.168.0.1

Keep in mind that random IPs will often point to hosts that don’t exist or are offline. An IDS and a competent admin can filter those out to home in on the real address.

A more advanced approach is to use so-called idle scanning. It’s a fascinating technique that relies on three simple facts:

  • During a SYN scan, the remote host replies with SYN/ACK if the port is open, and with RST if it’s closed.
  • A host that receives an unsolicited SYN/ACK should respond with RST, and it should ignore unsolicited RSTs.
  • Every IP packet sent by a host carries an IP identification field (IP ID), and many operating systems simply increment the IP ID for each packet they send.

The technique is to find an idle host—one that isn’t doing anything—but is up and able to respond to network requests. In addition, the host needs to run an old OS that increments the IPID field instead of randomizing it like modern systems do. You can do this with Nmap using the same -O -v flags (check the “IP ID Sequence Generation” line in the output) or with the Metasploit Framework, which is faster and more convenient:

> use auxiliary/scanner/ip/ipidseq
> set RHOSTS 192.168.0.1-192.168.0.255
> run

Next, run a port scan:

$ sudo nmap -sI IP-of-idle-host 192.168.0.1

For each port probe, Nmap first queries the idle “zombie” host and records its IPID. It then sends a SYN to the target, spoofing the zombie’s IP as the source, and queries the zombie again to compare the new IPID with the saved value. If the IPID has increased since the last check, the zombie must have sent a packet—specifically, an RST in response to a SYN/ACK from the target—which means the target port is open. If the IPID didn’t increase, the port is closed.

In today’s environment—now that Windows 95 is long gone—this technique is indeed hard to pull off, but it completely shifts suspicion away from you. The IDS will pin the scan on the idle host.

Bypassing IDS and Firewalls

Up front: today’s IDS and firewalls are far smarter than the ones around when Nmap first added evasion features. So some of the techniques described here may no longer work, but that’s no reason to skip them—there’s still plenty of legacy, borderline prehistoric gear out there on the internet.

To start with, even without extra options, Nmap can’t bypass a firewall, but it can detect one. In a SYN scan, port state is inferred from the target’s response: SYN/ACK means open, RST means closed. Firewalls often drop packets to filtered ports to save CPU (on Linux, a common iptables policy is to use -j DROP). When Nmap sees no response to its probes, it flags those ports as filtered.

Another way to detect a firewall is to have Nmap generate “impossible” packets—such as packets with no flags set (-sN), FIN-only packets (-sF), and Xmas packets with the FIN, PSH, and URG flags set (-sX). The RFCs describe how stacks should behave in each of these cases, so Nmap treats any deviation from that RFC-defined behavior as evidence of a firewall.

Many firewalls can be evaded, and you can accurately determine whether a port is being filtered. To do this, you can use an ACK scan:

$ sudo nmap -sA 192.168.0.1

The idea is this: the firewall should block all new TCP connections to the port, but it must not interfere with packets that belong to already established connections. A simple way to do that is to drop all SYN packets (used to establish a connection) while allowing ACK packets (used to send packets within an already open connection).

There’s one nuance, though. There are so‑called stateful firewalls: they track connection state and inspect packet fields like the IP address and TCP sequence number to tell which packets truly belong to an already established connection and which were sent by Nmap as part of an ACK scan. iptables on Linux can operate in both modes, but by default it’s not stateful—that’s the higher‑performance option.

You can figure out what type of firewall is in use by running a SYN scan followed immediately by an ACK scan:

$ sudo nmap -sS 192.168.0.1
$ sudo nmap -sA 192.168.0.1

If, in the second case, ports that were marked as filtered during a SYN scan now show as unfiltered, then you’re not dealing with a stateful firewall.

Another option is to try bypassing the firewall by changing the outgoing port number:

$ sudo nmap --source-port 53 192.168.0.1

This exploits a timeworn firewall misconfiguration where an admin allows all inbound traffic (including TCP) from port 53 so applications can perform DNS lookups without restriction. It’s less common today, but, as experience shows, incompetence doesn’t fade with time.

Among other things, Nmap provides features to conceal scans from firewalls and IDS systems:

$ sudo nmap -f 192.168.0.1

In this case, Nmap splits packets into tiny 8-byte fragments. The idea is that a firewall or IDS might fail to reassemble the fragments and inspect the header—either due to poor implementation or for performance reasons—and will simply let the packet through or drop it.

$ sudo nmap --mtu 16 192.168.0.1

Same idea, but with the ability to control the packet size (16 in this example). This can be used against firewalls and IDS that detect Nmap scans by analyzing fragment sizes.

$ sudo nmap --data-length 25 192.168.0.1

Appends the specified number of random bytes to the end of the packet. The goal is the same as in the previous case: to fool an IDS that might detect scanning by analyzing packet size (Nmap always sends 40-byte packets when using TCP).

Using Nmap for Host Discovery

Although Nmap is best known as a port scanner, it’s also an excellent tool for discovering hosts on a network. You can point it at any number of targets and get “ping” results for thousands of hosts in just a few seconds. The catch is that it doesn’t ping hosts the same way the familiar ping utility does. By default, before starting a port scan, Nmap sends several different probe packets to verify that a host is reachable:

  • ICMP Echo Request — the same mechanism used by ping.
  • TCP SYN packet to port 443.
  • TCP ACK packet to port 80.
  • ICMP Timestamp Request.

You need multiple probing methods to work around firewalls and environments where, for example, the OS or network gear is configured not to respond to ICMP Echo (ping) requests—a common practice today.

You can easily disable host discovery using the -PN option; Nmap will even suggest this if it can’t determine whether the host is up:

$ sudo nmap -PN 192.168.0.1

Usually there’s not much sense in doing that, but the opposite—disabling the port scanner—is actually very useful for checking the reachability of a large number of hosts:

$ sudo nmap -sn 192.168.0.1-255

This command tells Nmap to scan addresses from 192.168.0.1 through 192.168.0.255. A more convenient alternative:

$ sudo nmap -sn 192.168.0.*

Here’s how to have Nmap scan the entire subnet:

$ sudo nmap -sn 192.168.0.0/24

Or, alternatively, save the required addresses to a file and have it scan them:

$ sudo nmap -sn -iL /path/to/file

If you omit the -sn flag, Nmap will not only check whether hosts are up, but also scan their ports.

There are plenty of ping techniques, too. Nmap supports checking whether a host is up by sending a SYN packet to a specified port:

$ sudo nmap -sn -PS80 192.168.0.1

ACK packet:

$ sudo nmap -sn -PA80 192.168.0.1

UDP packet:

$ sudo nmap -sn -PU53 192.168.0.1

ICMP Echo request:

$ sudo nmap -sn -PE 192.168.0.1

ICMP timestamp:

$ sudo nmap -sn -PP 192.168.0.1

All of them can be combined:

$ sudo nmap -sn -PE -PS443 -PA80 -PP 192.168.0.1
Nmap detected only a single host on the local network
Nmap detected only a single host on the local network

Brute-forcing, dirbusting (directory enumeration), DoS, and other attacks

A relatively new Nmap feature is its scripting support, which extends the scanner’s functionality. Nmap ships with more than 500 scripts, each belonging to one or more of fourteen categories:

  • auth — authentication checks. Example: ftp-anon tries anonymous login on an FTP server and lists files, flagging those that are writable.
  • broadcast — various forms of network host discovery via broadcast. Example: broadcast-upnp-info searches for UPnP services.
  • brute — password brute-forcing techniques. Example: http-brute brute-forces web server credentials.
  • default — scripts that run automatically with the -A or -sC options. These are usually quick, lightweight scripts that gather extra host info, such as ftp-anon.
  • discovery — roughly equivalent to broadcast. Example: smb-enum-shares enumerates SMB shares.
  • dos — scripts for conducting denial-of-service attacks. Example: smb-vuln-regsvc-dos crashes Windows 2000 by exploiting MSRC8742.
  • exploit — exploitation or vulnerability checks. Example: smb-vuln-ms06-025 checks Windows hosts for MS06-025.
  • external — scripts that use external resources to enrich host information. Example: whois.
  • fuzzer — scripts that send unexpected or malformed data to the target to find vulnerabilities or trigger DoS. Example: dns-fuzz.
  • intrusive — scripts that perform active, potentially disruptive actions against the host. Example: snmp-brute brute-forces an SNMP server.
  • malware — checks for signs of malware or backdoors. Example: smtp-strangeport looks for SMTP running on a nonstandard port, which may indicate a spam-sending trojan.
  • safe — “safe” scripts that avoid intrusive actions, don’t flood the network, and don’t exploit vulnerabilities. Example: ssh-hostkey retrieves an SSH server’s public keys.
  • version — service version detection. Example: pptp-version prints additional information about a PPTP server.
  • vuln — checks services for known vulnerabilities.

If you specify the -A or -sC options, scripts in the default category will run automatically. To run scripts from other categories, use the –script option:

$ sudo nmap --script "default and safe" 192.168.0.1

You can invert the selection by having Nmap run all scripts except those in the specified category:

$ sudo nmap --script "not intrusive" 192.168.0.1

You can also specify the script by name (http-enum performs HTTP server dirbusting):

$ sudo nmap -p80 --script "http-enum" 192.168.0.1

Or tell Nmap to run all HTTP-related scripts:

$ sudo nmap -p80 --script "http-*" 192.168.0.1

You can find the scripts themselves, along with descriptions and usage examples, in the /usr/share/nmap/scripts directory.

Dirbusting with Nmap
Dirbusting with Nmap

Spinning up a web server (yes, really)

Few people realize that Nmap ships with a utility called ncat. It’s a counterpart to the famous netcat—a versatile networking tool you can use to test network services, run remote commands, transfer files, pipe audio over the network, listen on ports, and do many other useful things.

You can also use it to run a simple web server:

$ ncat -lk -p 8080 --sh-exec "echo -e 'HTTP/1.1 200 OK'; cat index.html"

Nmap’s Six Port States

  • open — the port is open
  • closed — the port is closed
  • filtered — the port is filtered; Nmap can’t determine whether it’s open or closed
  • unfiltered — the port is not filtered; Nmap can’t determine whether it’s open or closed (this result is only possible with an ACK scan)
  • open|filtered — the port is either open or filtered
  • closed|filtered — the port is either closed or filtered (this result is only possible with an Idle scan)

Conclusion

This article covers only a portion of Nmap’s capabilities—albeit the most useful ones. As you’ve seen, Nmap’s functionality extends far beyond port scanning. It’s a powerful, sophisticated tool whose code has been refined over decades. It’s fast, reliable, and incredibly feature-rich. Best of all, it’s completely free and runs almost everywhere.

it? Share: