Enumeration is one of the most critical and underestimated phases in penetration testing. Its true objective isn’t just to gain access to a system, but to discover how access might be possible. This means identifying services, configurations, and information leaks that reveal potential attack paths. Rather than just scanning passively, effective enumeration involves actively interacting with services, learning their protocols, expected inputs, and outputs. The more precise and detailed the information we gather, the faster and more efficiently we can identify weak points—just like finding lost keys is easier when we’re told exactly where to look, not just what room they’re in.
The core of enumeration comes down to two things: identifying functions or services we can interact with, and finding information that leads to more valuable information . Often, misconfigurations or insecure defaults are responsible for what we uncover. These are not necessarily due to technical limitations, but a poor security mindset or over-reliance on basic protections like firewalls and patches. Many mistakes during enumeration happen not because the tester failed to try enough tools, but because they didn’t understand the logic or structure behind the services they were analyzing.
Lastly, while automated tools are helpful, manual enumeration remains irreplaceable. Tools often depend on assumptions—like how fast a service should respond—and may classify slower ports as closed or filtered. This can cause critical services to be overlooked entirely. What if a key port is simply delayed, not closed? Overreliance on scan results without deeper investigation can lead to missed entry points and wasted hours chasing false negatives. The lesson is clear: enumeration isn't just about running scans—it's about questioning what those scans might miss.
Nmap (Network Mapper) is a powerful, open-source tool widely used for network discovery, auditing, and security assessments. Developed in C, C++, Python, and Lua, it scans networks using raw packets to identify live hosts, open ports, running services (with version info), and even the target's operating system. It also assists in identifying firewall rules, IDS/IPS presence, and general network configurations.
It also supports both basic and advanced scanning techniques to adapt to different network environments and evasion strategies. Its architecture includes several key scanning functionalities: host discovery, port scanning, service enumeration, OS detection, and scriptable automation through the Nmap Scripting Engine (NSE). The basic syntax follows this structure:
$ nmap {scan types} {options} {target}
It is always good practice to save every scan result. This supports reporting, comparison, and troubleshooting, especially since different tools may provide slightly different outputs. Nmap offers various output formats, including XML, grepable, and normal formats.
Normal format
$ nmap 10.10.16.6 -oN result.nmap
XML format
$ nmap 10.10.16.6 -oX result.xml
Grepable format
$ nmap 10.10.16.6 -oG result.gnmap
All formats
$ nmap 10.10.16.6 -oA result
Finally, Nmap provides several performance options to speed up scans across large networks or limited-bandwidth environments. These options include timing templates (-T0 to -T5), timeout settings (--max-rtt-timeout), parallelism, rate limits (--min-rate), and retry control (--max-retries).
When scanning large networks, the Round-Trip Time (RTT) can impact speed. Nmap’s default --min-rtt-timeout is 100ms. Reducing this can speed up scans, but might cause missed results.
By default, Nmap retries sending packets 10 times. Setting --max-retries 0 skips retries entirely, reducing scan time but risking missed open ports.
Using --min-rate increases the number of packets sent per second. When whitelisted or testing internally, setting a high rate like --min-rate 300 significantly speeds up scans.
Nmap includes six timing templates to automate performance tuning:
Each level changes options like RTT, retries, delay, and packet rate. For example, an -T5
scan of
256 hosts finished in 18s compared to 32s with default settings—without missing open ports.
When performing an internal network penetration test, one of the first steps is identifying which systems are live on the network. Nmap's host discovery features allow us to scan and detect active hosts efficiently in a network range. A common and effective method is using ICMP echo requests (ping), which help determine whether a target responds (is alive). Let's introduce 4 scenarios where we could use Nmap to discover hosts:
Keep in mind that this technique relies on the host firewall settings. If ICMP is blocked, hosts may appear offline. Alternative detection methods will be discussed in the Firewall and IDS Evasion section.
Scan Network Range
To scan a network range like 10.129.2.0/24 we can use the following command:
$ sudo nmap -sn 10.129.2.0/24
-sn: Disables port scanning.
Scan IP List
During an internal penetration test, it is not uncommon for us to be provided with an IP list with the hosts we need to test. Nmap also gives us the option of working with lists and reading the hosts from this list instead of manually defining or typing them in.
$ sudo nmap -sn -iL hosts.lst
-iL: Performs defined scans against targets in provided 'hosts.lst' list.
-sn: Disables port scanning
Where hosts.lst looks like:
$ cat hosts.lst
10.129.2.4
10.129.2.10
10.129.2.11
10.129.2.18
10.129.2.19
10.129.2.20
10.129.2.28
Remember, some hosts ignore the default ICMP echo requests because of their firewall configurations. Since Nmap does not receive a response, it marks those hosts as inactive.
Scan Multiple IPs
It can also happen that we only need to scan a small part of a network. An alternative to the method we used last time is to specify multiple IP addresses.
$ sudo -sn nmap 10.129.2.18 10.129.2.19 10.129.2.20
-sn: Disables port scanning
If these IP addresses are next to each other, we can also define the range in the respective octet.
$ sudo nmap -sn 10.129.2.18-20
-sn: Disables port scanning
Scan Single IP
Nmap uses various techniques to determine whether a target host is alive before scanning its ports. Two of the most important methods are ICMP Echo Requests and ARP Requests.
1. ICMP Echo Request (-PE): This is the classic "ping". Nmap sends an ICMP Echo Request to the target saying “hello, are you alive?” If the target responds with an ICMP Echo Reply, it confirms that the host is up.
2. ARP Request: This is used in local networks. It sends an ARP packet asking “who has IP X? Tell me your MAC address.” If the target replies, it is considered alive, even if it blocks ICMP.
By default, when you run a command like:
$ sudo nmap -sn 10.129.2.0/24
Nmap first checks if the host is up using a ping. Depending on your network context, this ping may be:
To force Nmap to use ICMP instead of ARP, use:
$ nmap -sn -PE 192.168.1.10 --packet-trace --reason
-PE: Performs the ping scan by using 'ICMP Echo requests' against the target.
--reason: Displays the reason for specific result.
--packet-trace: Shows all packets sent and received.
Also we have:
--disable-arp-ping: Disables ARP ping.
-Pn: Disable the ICMP echo requests
Finally, we can introduce the concept of TTL. TTL (Time To Live) is a field in the IP protocol that defines the maximum number of hops (routers) a packet can traverse before being discarded. This mechanism helps prevent infinite loops in the network. Different OSes typically use different initial TTL values:
There are a total of 6 different states for a scanned port we can obtain:
When a port is marked as filtered, it usually means that a firewall is actively dropping or
rejecting packets. If a packet is dropped silently, Nmap receives no reply from the host
and
will retry the request (by default, up to 10 times) to confirm the state. This behavior helps detect packet
loss or filtering, but increases scan time.
To investigate filtered ports, we can use --packet-trace
to monitor the packets sent and
received.
Nmap scans the top 1000 TCP ports by default using the SYN
scan (-sS
), when run as root, since it requires raw socket
permissions.When is executed as a non-root user, it defaults to the TCP connect
scan (-sT
), which uses standard system calls instead of raw packets.
You can specify which ports to scan using the following options:
-p 22,25,80,139,445
: Manually define specific ports.-p 22-445
: Define a range of ports.--top-ports=10
: Scan the top 10 most common ports based on Nmap's
frequency
database.-p-
: Scan all 65,535 TCP ports.-F
: Perform a fast scan on the top 100 ports.TCP Connect Scan (-sT
)
The CP Connect Scan (-sT
) uses the full TCP three-way
handshake to determine whether a port is open, closed, or
filtered. Nmap sends a SYN
packet to the target, and if it receives a
SYN-ACK
, the port is considered open. If an RST
is returned, the port is closed.
This scan is also known as a full TCP connect scan and is very accurate because it
completes
the TCP handshake. However, it is not stealthy: completing the handshake means the scan is
logged by most systems and easily detected by modern IDS/IPS solutions.
Despite being noisy, this method is sometimes referred to as a more polite scan since it
interacts with services like a legitimate client, minimizing the risk of crashing them or causing
instability.
It is particularly useful when accuracy is prioritized over stealth.
The Connect Scan also works well against systems with personal firewalls that drop inbound
traffic but allow outbound connections. Since the handshake originates from the target system back to the
scanner, the firewall may not block the scan.
One downside is that the scan is typically slower than others, as it waits for a full
response from each packet, which adds latency—especially if the target is unresponsive or under load.
By contrast, the SYN scan (-sS
), often called a half-open
scan,
does not complete the handshake and is therefore more stealthy. It avoids generating full connection logs,
but
advanced IDS/IPS solutions are increasingly capable of detecting these as well.
TCP Connect Scan (-sS
)
The SYN Scan (-sS
) is one of the most commonly used scanning techniques in Nmap. Also known as
a
half-open scan, it sends a SYN
packet to the target port and analyzes the
response without completing the full TCP handshake.
If the target replies with a SYN-ACK
, the port is considered open. If it
responds with an RST
, the port is closed. When there is no response or an ICMP
unreachable message is received, the port is marked as filtered.
This scan is popular because it is fast, efficient, and generally more
stealthy than a TCP Connect scan. It does not complete the three-way handshake, which
reduces
the likelihood of being logged by the target system or triggering alerts on IDS/IPS
solutions.
The SYN scan requires root privileges or administrative access since it uses raw sockets to
craft the TCP packets manually. Without such permissions, Nmap will fall back to using a TCP Connect scan
(-sT
).
While many administrators configure firewalls for TCP ports, UDP ports are often neglected.
UDP is stateless and does not use a handshake, so no response is received if the port is
open, making scans slower and less reliable. Nmap's -sU
scan
sends empty
datagrams, but unless the service replies, it’s difficult to determine the port’s status.
Some ports return a response and are shown as open (e.g., 137, 5353), while others are marked as open|filtered due to lack of replies. A received ICMP Type 3 Code 3 ("port unreachable") response indicates the port is definitively closed. If no response is received and no ICMP errors are returned, the port is labeled open|filtered, meaning Nmap cannot determine the state with certainty.
During a penetration test, it's crucial to accurately identify the services running on the target, including their version numbers. This enables targeted vulnerability research and helps locate precise exploits. Detecting the exact version of a service is often the key to successful exploitation.
A good approach starts with a quick scan for known open ports and then escalates to a full port scan combined
with version detection using -sV
. This provides banner grabbing and protocol fingerprinting. For
full scans, we can press Space to check the progress or use --stats-every
to update
automatically.
$ sudo nmap 10.129.2.28 -p- -sV --stats-every=5s
To increase verbosity and get immediate feedback on open ports, use -v
or -vv
.
$ sudo nmap 10.129.2.28 -p- -sV -v
Below is an example of a full scan revealing multiple services and their versions:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu
25/tcp open smtp Postfix smtpd
80/tcp open http Apache httpd 2.4.29
Nmap identifies service versions using banner grabbing. If no banner is detected, it attempts signature matching, which may extend scan duration. Occasionally, banner details are missed by Nmap but are visible via manual inspection.
If you suspect Nmap has missed banner information, you can grab it manually using nc
(netcat):
$ nc -nv 10.129.2.28 25
220 inlane ESMTP Postfix (Ubuntu)
Capturing the network traffic with tcpdump
shows how this banner is delivered:
$ sudo tcpdump -i eth0 host 10.10.14.2 and 10.129.2.28
TCP flow:
The Nmap Scripting Engine (NSE) extends Nmap’s functionality by allowing advanced interactions with services through custom Lua scripts. These scripts are grouped into 14 categories, each designed to perform a specific type of analysis, such as brute-force, vulnerability detection, service discovery, or authentication testing.
Category | Description |
---|---|
auth | Determines authentication credentials. |
broadcast | Performs host discovery via broadcasting and adds found hosts to scans. |
brute | Performs brute-force logins using credential dictionaries. |
default | Default scripts run with the -sC option. |
discovery | Discovers available services and information about the target. |
dos | Tests for denial of service vulnerabilities (may be disruptive). |
exploit | Attempts to exploit known vulnerabilities on target ports. |
external | Uses external resources or APIs for additional scan analysis. |
fuzzer | Sends malformed input to discover unexpected behavior or bugs. |
intrusive | Scripts that may disrupt target systems or reveal sensitive data. |
malware | Detects signs of malware on the target system. |
safe | Non-intrusive scripts safe to run in production environments. |
version | Enhances version detection during scans. |
vuln | Checks for known vulnerabilities using pre-defined scripts. |
You can use NSE in three main ways:
The -A
option combines multiple capabilities: service version detection (-sV
), OS
detection (-O
), traceroute, and default NSE scripts. It gives a broad and detailed overview of
the target system:
$ sudo nmap 10.129.2.28 -p 80 -A
By using the vuln
category, NSE can check known vulnerabilities in detected services. For
instance:
$ sudo nmap 10.129.2.28 -p 80 -sV --script vuln
During penetration tests, it is common to encounter network defenses like firewalls and IDS/IPS systems. Nmap offers multiple evasion techniques to bypass these barriers and perform reconnaissance without detection. These mechanisms control incoming traffic and may block scans that appear suspicious or unauthorized. Understanding their behavior allows us to craft smarter, stealthier scans.
Firewalls are network security systems that monitor and control incoming and outgoing traffic based on predefined rules. Their primary function is to block unauthorized access attempts from external networks while allowing legitimate communication. They inspect packets and determine whether to pass, ignore, or reject them, helping to mitigate potentially dangerous connections.
Like the firewall, the intrusion detection system (IDS) and intrusion prevention system (IPS) are also software-based components. IDS scans the network for potential attacks, analyzes them, and reports any detected attacks. IPS complements IDS by taking specific defensive measures if a potential attack should have been detected. The analysis of such attacks is based on pattern matching and signatures. If specific patterns are detected, such as a service detection scan, IPS may prevent the pending connection attempts.
When a port is marked as filtered by Nmap, it usually means that a firewall is interfering with the scan. This can happen in two ways: the packet is dropped (no response from the host), or it is rejected (the host sends a response indicating denial).
Dropped packets are simply ignored by the firewall, making it seem as if the port doesn't exist. Rejected packets, however, typically trigger an RST flag (in TCP) or generate ICMP error messages such as:
One effective technique to probe such ports is Nmap's ACK scan (-sA). Unlike SYN (-sS) or Connect (-sT) scans, ACK scans send packets with only the ACK flag set. Since firewalls commonly block SYN traffic but allow ACK traffic (assuming it's part of an existing connection), this method is more likely to pass through firewall filters.
The host will typically respond with an RST packet regardless of whether the port is open or closed, allowing us to infer whether the port is unfiltered (we get a response) or filtered (no response). This makes the ACK scan an ideal method for detecting the presence of a firewall. Let's see an example:
$ sudo nmap 10.129.2.28 -p 21,22,25 -sS -Pn -n --disable-arp-ping --packet-trace
SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:22 S ttl=53 id=22412 iplen=44 seq=4092255222 win=1024
SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:25 S ttl=50 id=62291 iplen=44 seq=4092255222 win=1024
SENT (0.0278s) TCP 10.10.14.2:57347 > 10.129.2.28:21 S ttl=58 id=38696 iplen=44 seq=4092255222 win=1024
RCVD (0.0329s) ICMP [10.129.2.28 > 10.10.14.2 Port 21 unreachable (type=3/code=3) ] IP [ttl=64 id=40884 iplen=72 ]
RCVD (0.0341s) TCP 10.129.2.28:22 > 10.10.14.2:57347 SA ttl=64 id=0 iplen=44 seq=1153454414 win=64240
RCVD (1.0386s) TCP 10.129.2.28:22 > 10.10.14.2:57347 SA ttl=64 id=0 iplen=44 seq=1153454414 win=64240
SENT (1.1366s) TCP 10.10.14.2:57348 > 10.129.2.28:25 S ttl=44 id=6796 iplen=44 seq=4092320759 win=1024
Nmap scan report for 10.129.2.28
Host is up (0.0053s latency).
PORT STATE SERVICE
21/tcp filtered ftp
22/tcp open ssh
25/tcp filtered smtp
Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds
$ sudo nmap 10.129.2.28 -p 21,22,25 -sA -Pn -n --disable-arp-ping --packet-trace
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 14:57 CEST
SENT (0.0422s) TCP 10.10.14.2:49343 > 10.129.2.28:21 A ttl=49 id=12381 iplen=40 seq=0 win=1024
SENT (0.0423s) TCP 10.10.14.2:49343 > 10.129.2.28:22 A ttl=41 id=5146 iplen=40 seq=0 win=1024
SENT (0.0423s) TCP 10.10.14.2:49343 > 10.129.2.28:25 A ttl=49 id=5800 iplen=40 seq=0 win=1024
RCVD (0.1252s) ICMP [10.129.2.28 > 10.10.14.2 Port 21 unreachable (type=3/code=3) ] IP [ttl=64 id=55628 iplen=68 ]
RCVD (0.1268s) TCP 10.129.2.28:22 > 10.10.14.2:49343 R ttl=64 id=0 iplen=40 seq=1660784500 win=0
SENT (1.3837s) TCP 10.10.14.2:49344 > 10.129.2.28:25 A ttl=59 id=21915 iplen=40 seq=0 win=1024
Nmap scan report for 10.129.2.28
Host is up (0.083s latency).
PORT STATE SERVICE
21/tcp filtered ftp
22/tcp unfiltered ssh
25/tcp filtered smtp
Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds
Please pay attention to the RCVD packets and its set flag we receive from our target. With the SYN scan (-sS) our target tries to establish the TCP connection by sending a packet back with the SYN-ACK (SA) flags set and with the ACK scan (-sA) we get the RST flag because TCP port 22 is open. For the TCP port 25, we do not receive any packets back, which indicates that the packets will be dropped.
IDS and IPS are passive monitoring tools that inspect all traffic between hosts. IDS identifies suspicious behavior and alerts administrators, while IPS takes automated action to prevent or block potentially harmful traffic. Detecting such systems is more difficult than detecting firewalls. Since IDS/IPS tools rely on pattern recognition and signatures, a typical Nmap scan can trigger alerts — especially if it includes aggressive service detection or probing. A common method to identify if an IPS is active is to use multiple VPSs (Virtual Private Servers) with different IPs. If a scan from one VPS gets blocked, and the IP loses access to the network, we can assume that security mechanisms like IPS have taken defensive action. We can then rotate to another VPS to continue testing. To avoid detection, we should limit the intensity of scans and mimic normal traffic behavior. Testing how the target network reacts to small, isolated scans—such as a port scan on a single service—can reveal if monitoring is in place. If the scan leads to a blocked IP or connection timeout, that’s a sign of an active IDS/IPS setup. Based on these observations, it's often necessary to reduce scan aggressiveness and use stealth techniques such as decoys, packet fragmentation, or adjusting timing to evade detection.
In some environments, administrators block access from certain IP ranges or countries as a standard
precaution. Additionally, IPS systems may detect and block scanning behavior. To avoid
direct
attribution, Nmap offers the decoy scan option (-D), which injects
multiple
fake
IP addresses into the scan traffic.
This technique disguises the real source IP by placing it randomly among several
spoofed IPs. For example, -D RND:5
inserts 5 randomly generated decoys, with
your real IP hidden between them.
One important consideration is that decoys must be reachable. If they are not alive, target
services may become unresponsive due to SYN flood protection, making the scan ineffective.
Decoy scanning is a useful evasion technique when dealing with strict IP filtering or
monitoring, but it must be used carefully to avoid misconfigurations or unintentionally blocking access to
services.