There are 3 cardinal rules when trying to avoid detection that apply no matter what tools you are using:
- Less is more. The less traffic you generate, the less the IDS has to match its rules against. You can also avoid packet-counting thresholds this way.
- Blend in. If your traffic looks like legitimate traffic, it will be harder to catch without drowning in false-positives.
- Do your research. Reading this blog post is insufficient. You have to know what kind of setup your target is using and tune your approach to what works best.
- Use public DNS records from sites like Robtex for host discovery.
- Use hosted scan data and scanners like Shodan, scans.io, and HackerTarget.com.
- Use search engines and Google dorking to look for interesting stuff.
- Use nmap -sL to do reverse-DNS lookups on big subnets looking for interesting names.
The other important thing is to do your research regarding your targets and their defenses. By searching job postings, using passive detection, and mapping rules and thresholds, you should get a good idea of what kind of defense systems are being used, how they are configured, and what the typical response actions are. Without this information, you are working blind and just guessing what behaviors to change. Take full advantage of weaknesses: if their IDS is vulnerable to fragmentation bypass, use fragmentation and don't worry about most of these restrictions!
Now let's examine the trouble spots we identified in Nmap's behavior.
First, there's the general problem of Nmap's raw packets being unique and fingerprintable. A good way to avoid this for TCP scans is to use the TCP Connect scan (-sT) instead of the SYN scan (-sS). This uses your OS's native socket calls to make connections, which means that the packets will blend in with other connections from valid clients. There are downsides in performance and level of detail (TTL info that can be used to map firewall rules is not available, for instance) but these are usually minimal in an IDS-evasion scenario.
"But wait," you say, "Isn't SYN scan the 'stealth' option?" Yes it is—in 1997. If your defense technology consists of watching daemon logs for aborted connection attempts, then TCP SYN scan is completely invisible. But as we discussed last time, SYN scan sticks out like a sore thumb to a stateful IDS. The combination of unique TCP options and unusual packet sequence make it a poor choice for IDS evasion.
Side note: A patch to allow a user to override the TCP Window size in SYN scan was just posted to the Nmap development list. I haven't tested it at all, but it would help with one aspect of this detection.
Next, there's the specific problem of Nmap's ICMP Echo Request host discovery option (-PE, used by default with root privilege) sending packets without a body. There are a few different options that can be used here: --data-length has been around since before Nmap 3.00 and appends a specified number of random bytes to the end of all raw packets. This avoids the signature directly, but still could look suspicious because most ping tools use a well-known static string. In the latest versions (beginning with 6.49BETA1), you can also use --data or --data-string to specify particular payloads to use. You'll have to separate the ICMP host discovery Nmap commands from the other uses of Nmap, though, since the data gets appended to every packet, which is unexpected and weird.
I'm mostly going to skip over OS detection, because there's no way to make it more stealthy. Because it depends on sending a bunch of strange-looking packets in a specific order, it will always be easy to detect. Avoid -O and -A if you are at all concerned with avoiding detection.
The cautions regarding excessive fragmentation are best handled by doing your research. Not all IDS will complain about this, and many of them will actually be bypassed by it (which is why the -f option was created in the first place). If you probe your target's defenses before trying large-scale enumeration, you'll know whether or not -f will help or harm you.
The performance impact of TCP Connect scan should not cause you problems because you will be artificially slowing down your progress to avoid timing thresholds. A good way to do this is to start with the timing templates (-T[0-5]) and then apply some well-researched tweaks. -T3 is the default, so you obviously want to go slower than that, but -T0 slows you down to 4 packets per minute, which is ridiculous. Here are some options that are helpful in combination with -T2 and lower:
- --max-retries - At very reduced speeds, you can't often afford to spend extra packets confirming that a port is filtered. Set this to 1 or 2 and just accept that you might miss something due to a dropped packet here or there.
- --max-rate - The primary effect of -T[0-2] is to slow down the packet rate. If you don't remember or don't like the rate one of the templates uses, override it with this.
Another, more difficult way to hide your UDP scans is to actually edit the nmap-payloads file to change what payloads are used. This can be beneficial in the long run, but requires that you do your research. Since these are actually sent to service daemons on your target, proceed with caution. You could end up crashing something.
As always, the ultimate solution to IDS detection of -sV is not to use the option. That said, there are other ways to reduce the noise a bit. Using the --version-intensity option, you can reduce the number of different probes that Nmap will try before giving up on a service. This means losing some version information, but you can usually get an idea of the type of service running on a port if it is a common port for that service. Setting this option to 0 will send only the Null probe (connect and wait for banner) and any probes that have been specifically listed as pertaining to the scanned port in nmap-service-probes. As always, do your research and understand what kinds of probes will be sent to what ports.
In addition to the probes in the nmap-service-probes file, -sV implies "--script version" or "run all the NSE scripts in the 'version' category." In versions of Nmap prior to 6.49BETA1, you could only prevent these scripts from running by removing them from the script.db catalog or by building Nmap without NSE support (./configure --without-liblua). Now, however, the --version-intensity option passes through to the version scripts, which all check to be sure that it is not less than 7 before running.
If you are wild enough to try NSE scripts against an IDS-protected target, you should know how to read Lua, since the script sources are the final authority on what data is sent. But if you're just looking to get a little better at blending in, these tips should help:
- Use --script-args-file to pass script arguments to Nmap from a file. This will keep your command line clean and make it harder to accidentally miss one of the options you choose
- Obviously avoid dos, intrusive, and exploit category scripts.
- Use scripts by name instead of by category, so that you know exactly what will be run.
- Thoroughly read the documentation for each script you intend to use.
- Set http.useragent to something believable that blends in.