A port scan is a technique used to interrogate a host in order to see what TCP or UDP services are accessible from a particular IP address. Scanning a system can be an important step along the way toward a successful compromise, because it gives information to an attacker about services that may be accessed and attacked.
That said, a port scan can also be an important step to just seeing what services are available to talk to; there is nothing inherently malicious about a port scan by itself. You can liken a port scan to a person knocking on all the doors of a house. For any given door, if someone answers and the person just says, "Hello, nice to meet you," and then walks away, no harm is done. While the repeated knocking may be suspicious, a crime has probably not been committed unless the person attempts to enter the house. Still, if someone were to knock on all the doors of my house, I would want to know about it, because it may be a sign of someone collecting information about the best way to break in. Similarly, it's a good idea to detect port scans (subject to a tuning exercise to reduce false positives), and most network intrusion detection systems offer the ability to send alerts when systems are hit with a scan.
A port scan does not have to involve an exhaustive test for every possible port on a target system.3 If an attacker is skilled at compromising, say, OpenSSH 3.3 and BIND 4.9 servers, then it is of little use to find out if the remaining
3 The source and destination port fields in the TCP and UDP headers are 16 bits wide, so there are 65,536 (2A16) total ports (including port 0, which can be scanned by Nmap).
65,5334 ports also have servers bound to them. Furthermore, generating a noisy scan to test all ports on a system is a good way to set off IDS alarm bells, because it is much more likely that any reasonable port scan thresholds would be tripped. As an attacker, it is better to not call unnecessary attention to oneself. To make it even more difficult for an IDS to determine the real source of a scan, an attacker can also use Nmap's decoy (-D) option. This allows a port scan to be duplicated from several spoofed source addresses, so it appears to the target system as though it is being scanned by several independent sources simultaneously. The goal is to make it harder for any security administrator who may be watching IDS alerts to work out the real source of a scan.
Port scans of TCP ports can be accomplished using a surprising number of techniques. Each of these techniques looks slightly different on the wire as packets traverse a network, and we dedicate the next few sections (beginning with "TCP connect() Scans" and ending with "TCP Idle Scans" on page 59) to illustrating the major scanning techniques. Fortunately, the unequaled Nmap scanner (see http://www.insecure.org) has automated each of these techniques for us, and we use Nmap for all scan examples in this chapter. We launch scans against the iptablesfw system with the default iptables policy active (see Figure 3-2), and we will discuss the Nmap port-scanning techniques listed below:
• TCP FIN, XMAS, and NULL scans—(Nmap -sF, -sX, -sN)
In each of the following scans, the Nmap -P0 command line option is used to force Nmap to skip determining whether the iptablesfw system is up (i.e., host discovery is omitted) before sending a scan. From Nmap's perspective, each scanned port can be in one of three states:
open There is a server bound to the port, and it is accessible. closed There is no server bound to the port.
filtered There may be a server bound to the port, but attempts to communicate with it are blocked, and Nmap cannot determine if the port is open or closed.
TCP connect() Scans
When a normal client application attempts to communicate over a network to a server that is bound to a TCP port, the local TCP stack interacts with the
4 Even though port zero can be scanned by Nmap, operating systems do not allow servers to bind() to port zero.
remote stack on behalf of the client. Before any application layer data is transmitted, the two stacks must negotiate the parameters that govern the conversation that is about to take place between the client and server. This negotiation is the standard TCP three-way handshake and requires three packets, as shown in Figure 3-4.
Figure 3-4: TCP three-way handshake
The first packet, SYN (short for synchronize), is sent by the client to the server. This packet advertises the desired initial sequence number (among other things, such as the TCP window size and options such as whether Selective Acknowledgment is permissible) used for tracking data transmission across the TCP session to the server. If the SYN packet reaches an open port, the server TCP stack responds with a SYN/ACK to acknowledge the receipt of the initial sequence value from the client and to declare its own sequence number back to the client. The client receives the SYN/ACK and responds with an acknowledgment to the server. At this point, both sides have agreed on the connection parameters (including the initial sequence numbers), and the connection state is defined as established and ready to transfer data.
In the context of the TCP connect() scan, the scanner sends both the SYN and the ending ACK packet for each scanned port. Any normal user can scan a remote system in this mode with Nmap; no special privileges are required.
Below are some of the iptables log messages displayed from a SYN scan along with the Nmap output. You can see that the http and https ports are open, and the options portion of the SYN packet contains a substantial number of options:
Starting Nmap 4.01 ( http://www.insecure.org/nmap/ ) at 2007-07-03 00:32 EDT Interesting ports on 71.157.X.X:
(The 1670 ports scanned but not shown below are in state: filtered) PORT STATE SERVICE 80/tcp open http 443/tcp open https
Nmap finished: 1 IP address (1 host up) scanned in 30.835 seconds
[iptablesfw]# grep SYN /var/log/messages j tail -n 1 Jul 3 00:32:32 iptablesfw kernel: DROP IN=eth0 OUT=
MAC=00:1B:dB:B8:b6:e4:00:B0:48:80:4e:B7:08:00 SRC=144.202.X.X DST=71.157.X.X LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=6S148 DF PROTO=TCP SPT=43237 DPT=6SB WINDOW=5840 RES=0x00 SYN URGP=0 OPT (020405B40402080A362957720000000001030306)
A SYN or half-open scan is similar to a connect() scan in that the scanner sends a SYN packet to each TCP port in an effort to elicit a SYN/ACK or RST/ACK response that will show if the targeted port is open or closed. However, the scanning system never completes the three-way handshake because it deliberately fails to return the ACK packet to any open port that responds with a SYN/ACK. Therefore, a SYN scan is also known as a half-open scan because three-way handshakes are never given a chance to gracefully complete, as depicted in Figure 3-5.
Figure 3-5: TCP half-open scan
A SYN scan cannot be accomplished with the connect() system call because that call invokes the vanilla TCP stack code, which will respond with an ACK for each SYN/ACK received from the target. Hence, every SYN packet sent in a SYN scan must be crafted by a mechanism that bypasses the TCP stack altogether. This is commonly accomplished by using a raw socket to build a data structure that mimics a SYN packet when placed on the wire by the OS kernel.
RAW SOCKETS AND UNSOLICITED SYN/ACKS
Using a raw socket to craft a TCP SYN packet toward a remote system instead of using the connect() system call brings up an interesting issue. If the remote host responds with a SYN/ACK, then the local TCP stack on the scanning system receives the SYN/ACK, but the outbound SYN packet did not come from the local stack (because we manually crafted it via the raw socket), so the SYN/ACK is not part of a legitimate TCP handshake as far as the stack is concerned. Hence, the scanner's local stack sends a RST back to the target system, because the SYN/ACK appears to be unsolicited. You can stop this behavior on the scanning system by adding the following iptables rule to the OUTPUT chain before starting a scan with the command:
[ext_scanner]# iptables -I OUTPUT 1 -d target -p tcp --tcp-flags RST RST -j DROP
Nmap uses a raw socket to manually build the TCP SYN packets used within its SYN scan mode (-sS), the default scanning mode for privileged users. Because the characteristics of these packets are determined by Nmap directly (without the use of the local TCP stack), they differ significantly from TCP SYN packets that the stack would normally have generated. For example, if we initiate a web session to http://www.google.com with a web browser and use tcpdump to display the SYN packet from our local Linux TCP stack, we see the following.
[iptablesfw]# tcpdump -i eth0 -l -nn port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
11:13:40.255182 IP 71.157.X.X.59603 > 220.127.116.11.80: S 2446075733:2446075733(0)win 5840 <mss 1460,sackOK,timestamp 277196169 0,nop,wscale 2>
Displayed above in bold are both the window size and the options portion of the TCP header. The specific values for each are defined by the local TCP stack and are used to negotiate a valid TCP session with the remote host.
Unlike the SYN packets generated by the real TCP stack, Nmap doesn't care about negotiating a real TCP session. The only thing Nmap is interested in is whether the port is open (Nmap receives a SYN/ACK), closed (Nmap receives a RST/ACK), or filtered (Nmap receives nothing) on the remote host. Hence, the TCP SYN packet that Nmap puts on the wire just needs to qualify to the remote host as a TCP packet with the SYN flag set so that the remote TCP stack either responds with a SYN/ACK, a RST/ACK, or nothing (if the port is filtered).
For versions of Nmap in the 3.x series, no TCP options are included within SYN packets used to scan remote systems, as shown below. (If options were included in the packet, then they would appear after the TCP window size, as shown here in bold.)
11:17:30.313099 IP 71.157.X.X.52831 > 18.104.22.168.80: S 2001815651:2001815651(0) win 3072
For recent versions of Nmap, the Maximum Segment Size (MSS) value is included within SYN packets that it sends, as shown below in bold.
15:55:57.521882 IP 71.157.X.X.58302 > 22.214.171.124.80: S 197554866:197554866(0) win 2048 <mss 1460>
If we run a SYN scan now against the iptablesfw system, the same ports that we saw from the connect() scan are reported as open, but there are fewer TCP options than for the connect() scan, as you can see. That is, the options string for the SYN scan is 020405B4 whereas the options string for the connect() scan in the previous section is 020405B40402080A362957720000000001030306.
Starting Nmap 4.01 ( http://www.insecure.org/nmap/ ) at 2007-07-03 00:27 EDT Interesting ports on 71.157.X.X:
(The 1670 ports scanned but not shown below are in state: filtered) PORT STATE SERVICE
80/tcp open http 443/tcp open https
Nmap finished: 1 IP address (1 host up) scanned in 22.334 seconds
[iptablesfw]# grep SYN /var/log/messages | tail -n 1 Jul 3 00:27:59 iptablesfw kernel: DROP IN=eth0 OUT=
MAC=00:13:d3:38:b6:e4:00:30:48:80:4e:37:08:00 SRC=144.202.X.X DST=71.157.X.X LEN=44 TOS=0x00 PREC=0x00 TTL=52 ID=21049 PROTO=TCP SPT=43996 DPT=658 WINDOW=1024 RES=0x00 SYN URGP=0 OPT (020405B4)
Was this article helpful?