SCANNING IPS-PROTECTED NETWORKS WITH NESSUS

Jacob Thompson, Independent Security Evaluators

A Nessus vulnerability scan is one component of an overall network-level security assessment. Frequently, networks are protected by an intrusion prevention system (IPS). IPS rules may block traffic when throughput, packet counts, or connection counts cross a predefined threshold, or when packets are sent to blacklisted ports. Nessus provides neither a facility to restrict the scan rate, nor any reliable method to restrict the TCP and UDP ports to which it sends traffic. This paper describes the difficulties encountered in controlling these aspects of Nessus scans and a workaround ISE developed using virtualization, packet filters, and traffic control.

Introduction

An early step in most network security assessments involves reconnaissance probes to identify the hosts and services accessible on the target network. Just as a real attacker would try to avoid detection, for various reasons so should the security analyst performing an assessment. Intrusion Prevention Systems (IPS) with port scan or threshold detection mechanisms, slow or congested networks, and even system administrators who may notice a declining network performance could both detect and block, rate-limit, filter, redirect, or otherwise screw up reconnaissance probes. Inaccurate probes can result in vulnerable services left undiscovered, and an overall inaccurate assessment. To avoid detection and its associated pitfalls, it is useful to limit the scan rate and breadth of hosts and services targetted.

The capabilities to both limit scan rates and to restrict the target destination ports are found in most free and commercial scans. For the most part, these implementations are effective, but Tenable's Nessus and possibly others, despite having the configuration options that appear to limit scan rates and restrict destination ports, do not work reliably. Security analysts who blindly trust these options are performing more intrusive scans than they may realize or intend. In this paper, ISE describes a workaround for controlling scan traffic that extends to any scanner.

Effective Rate Limiting Example

The Nmap scanner, a well-known, freely-available tool for discovering running hosts on networks and enumerating the network services running on them, provides some IPS-evasion functionality. Its documentation1 suggests using the --scan-delay flag to introduce a delay between successive packets. Further, the -p flag restricts the scanned ports to only those listed. Thus, a rate-limited scan of HTTP and HTTPS, with version detection, may be run with the following command:

nmap ‐sV ‐Pn ‐n ‐p 80,443 --scan-delay 0.5s target

The --scan-delay and -p options accomplish the two goals:

  • Nmap always waits one-half second between successive probes, and
  • since OS fingerprinting is disabled, Nmap restricts its probes to only the ports specified by the -p option.

Nessus, a commercial scanner, uses more powerful and more frequently updated plugins to identify specific service-level vulnerabilities. Unfortunately, in contrast to Nmap, Nessus has no facility to limit the scan rate in the form of "t seconds between probes," and its plugins often ignore the scan policy and generate traffic to ports that were specified to be ignored.

Nessus Limitations

Ideally, Nessus scan policies would support the constraints of adding a delay between successive probes and preventing traffic to all ports except an explicitly allowed white-list. First, we describe the configuration options available in Nessus that control the scan rate and ports to scan, and explain why these settings fail to impose those constraints. As of this writing, version 6.3.3 and plugin set 201503240515 is the latest version and plugin set of the Nessus scanner. This configuration was used to evaluate the limitations.

Issues Rate Limiting Scans

The Performance section of the scan policy contains the following settings:

  • Max Checks Per Host, which limits the number of checks that can execute simultaneously against a single host;
  • Max Hosts Per Scan which limits the number of hosts that can be scanned simultaneously;
  • Network Receive Timeout, which specifies the number of seconds Nessus will wait for a response to a probe unless overridden by a plugin;
  • Max Simultaneous TCP Sessions Per Host, which limits the maximum number of established TCP sessions on one host;
  • Max Simultaneous TCP Sessions Per Scan, which limits the maximum number of established TCP sessions (not effective when Max Hosts Per Scan is 1);

By setting the Max Checks Per Host, Max Hosts Per Scan, Max Simultaneous TCP Sessions Per Host, and Max Simultaneous TCP Sessions Per Scan options all to 1, Nessus performs the slowest scan possible. However, there is no control over the actual scan rate, and some plugins may be faster than others. Some of these settings, such as Network Receive Timeout, can be overridden and ignored by plugins entirely.

Issues Restricting Scanned Ports

The Nessus documentation2 suggests two scan policy options that might prevent the scanner from sending traffic to any ports other than those specified:

  • Port Scan Range; and
  • Consider Unscanned Ports as Closed.

The presumptive purpose of combining these options is to prevent the vulnerability scanner from sending traffic to any ports other than those listed under Port Scan Range. However, restricting the port scan range to 80, 443 and enabling Consider Unscanned Ports as Closed still sends traffic to other ports.

Another possibility, suggested in a Tenable forum post3, is to add reject rules to the nessusd.rules file for all ports other than those desired. That also fails.

Figure 1 shows the tcpdump logs traffic generated to ports other than 80 and 443, despite both of these configuration methods used to restrict Nessus's port range.

  # sudo tcpdump -i tap0 -p -n -q 'dst 10.0.1.194 and not dst port 80 and not dst port 443'
	   tcpdump: verbose output suppressed, use -v or -vv for full protocol decod
	   listening on tap0, link-type EN10MB (Ethernet), capture size 65535 byte
	   15:04:16.641700 IP 172.16.0.2.68 > 10.0.1.194.67: UDP, length 341
	   15:04:19.686034 IP 172.16.0.2.520 > 10.0.1.194.520: UDP, length 2
	   15:04:19.686249 IP 172.16.0.2.520 > 10.0.1.194.520: UDP, length 2
	   15:04:19.692011 IP 172.16.0.2 >10.0.1.194: ICMP type-#37, length 
	   15:04:20.706797 IP 172.16.0.2 > 10.0.1.194: ICMP address mask request, length 12
	   15:04:23.772784 IP 172.16.0.2 > 10.0.1.194: ICMP address mask request, length 1
	   15:04:26.884169 IP 172.16.0.2 > 10.0.1.194: ICMP address mask request, length 1
	   15:04:29.949591 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 1416
	   15:04:50.044859 IP 172.16.0.2.500 >10.0.1.194.500: UDP, length 46
	   15:05:10.124860 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 49
	   15:05:30.209046 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 55
	   15:05:50.294137 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 620
	   15:06:10.383545 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 74
	   15:06:30.475396 IP 172.16.0.2.500 > 10.0.1.194.500: UDP, length 87
	   15:06:50.571382 IP 172.16.0.2.56923 > 10.0.1.194.69: UDP, length 27
	   15:06:51.586310 IP 172.16.0.2.56923 > 10.0.1.194.69: UDP, length 2
	   15:06:52.600532 IP 172.16.0.2.56923 > 10.0.1.194.69: UDP, length 2
	   15:06:53.615139 IP 172.16.0.2.64052 > 10.0.1.194.69: UDP, length 2
	   15:06:54.629797 IP 172.16.0.2.64052 > 10.0.1.194.69: UDP, length 24
	   15:06:55.644433 IP 172.16.0.2.64052 > 10.0.1.194.69: UDP, length 2
	   15:06:56.660460 IP 172.16.0.2.43722 > 10.0.1.194.6969: UDP, length 1
	   15:07:11.679232 IP 172.16.0.2.3133 > 10.0.1.194.25771: tcp 
	   15:07:14.722295 IP 172.16.0.2.3133 > 10.0.1.194.25771: tcp 1
	   15:07:17.773582 IP 172.16.0.2.53448 > 10.0.1.194.0: tcp 
	   15:07:19.801784 IP 172.16.0.2.53448 > 10.0.1.194.0: tcp 
	   15:07:21.830032 IP 172.16.0.2.53448 > 10.0.1.194.0: tcp 
	   15:07:23.864593 IP 172.16.0.2.20 > 10.0.1.194.8888: tcp 0
	   15:07:23.876154 IP 172.16.0.2.35277 > 10.0.1.194.1900: UDP, length 25
	   15:07:24.176791 IP 172.16.0.2 > 10.0.1.194: ICMP time stamp query id 1 seq 1, length 3

Figure 1. Unwanted traffic generated by a Nessus scan despite setting both the scan policy and nessusd.rules file to scan only ports 80 and 443.
Aside from manually disabling plugins that generate unwanted traffic, there does not seem to be a way to reconfigure Nessus to reliably stop the traffic. Even if it were feasible to disable plugin-by-plugin, new plugins could be introduced that generate additional unwanted traffic.

Issues Employing Local Firewall

Since there is no simple, reliable way to prevent Nessus from generating the unwanted traffic, the alternative is to drop that traffic before it leaves the host using a firewall on the local machine. The operating system should first block all traffic to the target, and then explicitly allow only the desired ports. ISE tested this scenario using an iptables rule blocking the destination host entirely, but the traffic of Figure 1 was still generated. In particular, traffic still reaches other ports, including 67/udp (DHCP), 69/udp (TFTP), 500/tcp (ISAKMP), and 1900/udp (UPnP), as well as various ICMP requests.

The reason for the persistent, unwanted traffic is that Nessus uses the Linux packet socket interface to craft and deliver custom packets directly to the networking device. Packet sockets are created by calling socket with a first argument of PF_PACKET. As documented, "Packet sockets are not subject to the input or output firewall chains." Thus, iptables rules on the host machine are ineffective methods to prevent any Nessus plugins that use packet sockets from sending the unwanted packets.

	  # strace -f -e socket -p 633 2>&1 | grep PF_PACKET
		  [pid 10972] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10972] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 1
		  [pid 10939] socket(PF_PACKET, SOCK_RAW, 768) = 15

Figure 2. The strace command shows system calls that Nessus makes to create a packet socket.

Virtualization Solution

An easy way to get around the fact that Linux will not filter packet sockets is to run the scanner on a guest virtual machine (VM), and filter and shape the traffic on the VM host. Using qemu, network traffic passes between the guest VM's eth0 interface and the host's tap0 interface, as depicted in Figure 3.

Internet Access Route

Figure 3. Diagram showing how Nessus accesses the Internet from a guest VM through a host, allowing the host system to filter traffic, even if it is generated using a packet socket.
In this configuration, the guest performs no firewalling or filtering of its traffic. The guest (172.16.0.2) uses the host (172.16.0.1) as its default gateway. As network traffic originating from the guest is forwarded through the host, the host performs traffic shaping, forwarding, and masquerading (NAT) on that traffic. Traffic shaping slows down guest traffic to the desired rate, and by only selectively forwarding guest traffic, the host prevents Nessus from connecting to undesired ports. The VM host system configuration is given in the next two sections, and source code for a wrapper program that configures the tap interface and avoids the need to run qemu as root, as well as a shell script for running it, are given in the appendix.

Traffic Control

To achieve the constraint of at least a one-half second delay between probes, we use the Linux Token Bucket Filter queue discipline with the following parameters:

  • peakrate of 24000 bits per second, or two 1500-byte packets,
  • mtu of 1500 bytes, matching the MTU of the Ethernet interface,
  • latency of 5 seconds, so that packets that would be delayed by more than 5 seconds are instead dropped,
  • burst of 1500 bytes, to prevent bursts of traffic,
  • mpu of 1500 bytes, treating all packets as if they were 1500 bytes, so that the limit is two packets per second, rather than 24000 bits per second, and
  • rate of 23999 bits per second, the token creation rate. This must be strictly less than peakrate to be accepted by the kernel.

The resulting rules are shown in Figure 4.

	tc qdisc add dev eth0 handle 1:0 root prio priomap 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	tc qdisc add dev eth0 parent 1:1 handle 10:0 pfifo
	tc qdisc add dev eth0 parent 1:2 handle 20:0 pfifo
	tc qdisc add dev eth0 parent 1:3 handle 30:0 tbf rate 23999 mpu 1500 burst 1500 latency \ 
		   5s peakrate 24000 minburst 15000
	tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dst target/32 flowid 1:3

Figure 4. Linux Traffic Control rules to introduce an approximate one-half second delay between packets.

Firewall

The host machine operates as a normal Linux-based router. Traffic originating from the guest VM is subject to iptables firewall rules on the VM host -- even if generated by a packet socket. The commands shown in Figure 5 configure the host to forward traffic from the guest (172.16.0.2) if it is destined to TCP ports 80 or 443. UDP traffic, and TCP traffic to other ports, is dropped.

          iptables ‐P FORWARD DROP
          iptables ‐P FORWARD DROP
          iptables ‐A FORWARD ‐s 172.16.0.2 ‐d target ‐p tcp --dport 80 -j ACCEPT
          iptables ‐A FORWARD ‐s 172.16.0.2 ‐d target ‐p tcp --dport 443 -j ACCEPT
          iptables ‐A FORWARD ‐s 172.16.0.2 ‐d target ‐j REJECT
          iptables ‐A FORWARD ‐s 172.16.0.2 ‐j ACCEPT
          iptables ‐A FORWARD ‐d 172.16.0.2 ‐j ACCEPT
          iptables ‐t nat ‐A POSTROUTING ‐s 172.16.0.2 ‐j MASQUERADE
          sysctl net.ipv4.ip_forward=1

Figure 5. iptables firewall rules restricting traffic from the VM to ports 80 and 443 of a target.

Appendix

Qemu Startup Scirpt

#!/bin/sh

DIR=`dirname $0`
exec $DIR/qemu-tap-wrapper -hda $DIR/hda.qcow2 -m 1024 -usb 
-usbdevice tablet -net nic -enable-kvm

Qemu Tap Wrapper Program

<iframe src="qemu-tap-wrapper.c" width="80%"></iframe>

References

[1] Nmap's Documentation

[2] Tenable's 6.3 User Guide

[3] Nessusd.rules File Failing to Apply Reject Port Rule Correctly Discussion