IP Spoofing: Are You Really Who You Say You Are?
This is already my second installment of the security column for Sys Admin magazine. I would like to stress that it is vital for you, the reader, to provide us with input and questions related to the field of security. Only then can we continue our stream of subjects and improve the overall quality of the column. I encourage you to write and let me know about the questions you have and share your quest to repel the wily hacker.) You can email me directly at: firstname.lastname@example.org or send comments to: email@example.com.
The subject of this column is IP spoofing. Not long ago (about two years), this was the most iminent threat on the Internet. As the rumors spread, the truth/fiction ratio quickly took a turn for the worse. Rumor said that anybody on the Internet could pretend to be you, and nothing was safe anymore. Luckily, the threat turned out to be less spectacular than that, and now that the dust has settled, we can take a good look at what spoofing is all about.
I will discuss the "classical" spoofing for TCP connections, but also for UDP connections and some application-related protocols (email spoofing).
How to Do It
The basis of spoofing is pretending to be someone else. In the world of networking, your identity is linked to your network address, which on the Internet means your IP address. So, spoofing on the Internet is all about pretending to have the IP address of someone else. This sounds easier than it is.
Communications over the Internet are regulated by routers, which dynamically determine the best route by which to send a network packet. This process of determining the best route is based on the destination address, and possibly the originating address. In a spoofing attack, the destination address is the address of the "victim", and the originating address is the address of the machine you are pretending to be.
I will show you a number of examples of a spoofing attack. You will need to have a basic understanding of both UDP and TCP-based communications.
As you know, UDP is a connectionless protocol. This means that a UDP packet is put on the wire in the hope that it will reach its destination. There is no error checking or guaranteed delivery. UDP packets are very simple and are mainly used for low overhead protocols.
On the Internet, one of the heaviest users of UDP is DNS (Distributed Name Service). All queries for a certain name are done using UDP packets, which are sent to the DNS port of a name server. The reason for using UDP is that it has a low overhead, and queries can be executed quickly and efficiently.
On a local network, NFS is one of the power users of UDP. Normally, all data transported between a server and a client is layered on top of the UDP protocol. Due to its low overhead, UDP can make NFS a fast solution. However, due to its simplicity, it is also fairly easy to fake a UDP packet and thus spoof. A UDP packet looks roughly like this:
The header is made up of a number of fields. Most importantly:
There are no handshake fields or other things present. So, anyone who can make such a packet and put it on a wire is capable of spoofing. Handcrafting such a package can be done (in C) by declaring an array the size of the package and building an exact copy of the package in the array. On most UNIX machines, you can then open a RAW network device (i.e., talk directly to your network card) and hand over the array to this device. This device will take care of putting it on the wire. Imagine if someone could use this to fake responses of a DNS server on the Internet. He or she could then redirect all traffic via an intermediary system and monitor the traffic.
From the previous description, it is clear that spoofing a UDP package is fairly easy. Spoofing a TCP connection is a bit more difficult. This stems from the fact that TCP is a connection-based protocol. Before any data can be exchanged, both parties must agree on establishing a connection. I will briefly explain how a TCP connection is established.
A client that wants to connect to a server sends the server a so-called SYN packet, which is a (TCP) network packet with the SYN flag set in its header. This header also contains the sequence number the client wants to use. The sequence number is a 32-bit value used as an identifier. This identifier is used in the sliding window mechanism used to make TCP reliable. The only thing you need to remember is that the initial value of this sequence number can be chosen at random, but once chosen, it is incremented by one each time a packet is exchanged via the connection.
The SYN packet is received by the server, and when the server accepts the connection, it will return a SYN/ACK as an acknowledgement. This SYN/ACK packet contains the sequence number that the server wants to use for its side of the communications. After receiving this SYN/ACK packet, the client will return an ACK packet (after incrementing the sequence numbers). Once this is done, the connection is established, and data can be exchanged. This process is also known as a three-way handshake.
To spoof a TCP connection, a potential hacker has two problems. First of all, the hacker needs to know via which algorithm the server generates its initial sequence numbers. The hacker needs this to supply the correct number in its final ACK message confirming the connection and in all subsequent data packets.
Second, the hacker will never see the answer a server sends back, because the server returns those answers to the system the hacker is pretending to be. Due to the routing on the Internet, this system is typically located at a completely different location (e.g., on the local network of the victim). So, how does a TCP-based spoofing attack work?
The hacker needs to know how the victim generates its initial sequence numbers. The only way to find this out is either by making a lot of connections and checking the different sequence numbers, or by having access to the source of the networking software on the victim's machine. Although the latter possibility seems unlikely, it is not that difficult. Most UNIX systems have their networking roots in the BSD environment, and the sources of the BSD networking software are available on the Internet. The networking roots of NT are also accessible. So, if no special precautions have been taken, a potential hacker may be able to determine how these sequence numbers are generated. Professional auditing tools are available that have built-in tests to tell you how predictable these sequence numbers are.
Once the hacker knows the sequence numbers, the spoofing attack can commence. The hacker will handcraft a SYN packet, with the false sender address, and send it to the victim. The victim will receive this packet and send a SYN/ACK, not to the real sender, but to the system the hacker is pretending to be. If this system receives this SYN/ACK, it will send an error packet back to the victim, indicating it never sent a SYN in the first place. The hacker must make sure the victim does not receive these error packets, so he or she will try to crash the other system before launching the attack.
After sending the SYN, the hacker will handcraft and send an ACK packet, in which he or she will fill in the expected sequence number of the victim. If all is well, the victim now believes that it has established a connection with some trusted system. Once this connection is established, the hacker can send data to the victim that will be processed by the victim. Remember that the hacker never sees the data from the victim because these are delivered to the system the hacker is pretending to be. This kind of spoofing attack is often used to abuse the very weak authentication of the "r" utilities (rsh, rcmd, rexec). Once the hacker has gained access, he or she will try to overwrite or erase the password file for easier access to the system.
The last type of attack I will describe under the heading of "spoofing" are service-based spoofing attacks. Some Internet services (telnet, ftp) use a form of (not so strong) authentication. Other services, most notoriously SMTP (for email) do not use any authentication whatsoever. Thus, anyone can connect to that service (if the firewall allows) and send email. Most companies have enabled SMTP on their firewall to be able to receive email from the Internet, so it is child's play to send an email under a false sender address. It would be quite possible for your competitor to send an email under your name to someone else, pretending to be you.
Now that I've explained the inner workings of the spoofing attacks, let's consider the means by which we can prevent these from happening. For these measures, we must make a distinction between UDP/TCP-based spoofing and application spoofing.
To prevent application spoofing, it is necessary for each of the programs that "serve" the service to take appropriate measures. Newer versions of the sendmail program (starting with sendmail 8.8.4,) have some built-in features to prevent sendmail spoofing. These newer versions of sendmail also have a number of built-in configuration rules that can prevent, or at least minimize, false email. These rules are controlled by files typically located in the /etc/mail directory. These files are as follows:
ip_allow - This file contains the IP addresses of all systems that are allowed to use the machine as a relay (meaning that a client can deliver a message that needs to be relayed to another system; the mail server functions as a go between).
name_allow - It contains the names of all systems that are allowed to use the machine as a relay.
relay_allow - This file contains the names or addresses that the machine will relay email to.
deny - It contains the names of notorious email abusers, and no email is accepted originating from that system or domain.
Other services need to take care of their own measures, I have highlighted email because it is most vulnerable to an application spoofing attack.
It is not always possible to prevent a UDP or TCP-based spoofing attack, but you can do a number of things to minimize the risk. In most spoofing attacks, a packet is received on an interface you would not typically expect. For instance, you receive a network packet on the external interface of a firewall, but the source address lies within the network range on the internal interface.
You can prevent these packets from wreaking havoc by sharpening your packet filters. By rejecting all traffic on the external interface that has an internal source address, you can prevent external spoofing. Spoofing on the internal network is still possible. And in the case of UDP, there is not much else you can do without additional means. The only alternative is to convert as many services as possible from UDP to TCP.
In a TCP-based spoofing attack, there is one more thing you can do. You can use a true random number generator for generating the sequence numbers, and make it virtually impossible to guess the sequence number. Unfortunately, you cannot do this yourself, it is a part of the kernel (be it NT or UNIX). So, if you are running an old version of your OS, you need to upgrade.
Although spoofing attacks have disappeared somewhat from the limelight, they still pose a real threat. (The number of threats only grows; it does not shrink.) By understanding how these attacks work, you can find a possible cure and solve most of the problems related to these attacks. In my opinion, the focus will slowly shift to application-related spoofing in which a hackers abuse weaknesses in a particular service to send or receive information under a false name. A most notorious example is sendmail, which, when not properly configured, allows anyone to send email as firstname.lastname@example.org.
About the Author
Arthur Donkers graduated from the Delft University of Technology with a degree in Electrical Engineering and a major in Computer Architecture. Since then he has worked for a number of major software houses in the Netherlands. His primary field of interest is in datacommunications, especially the security aspects involved. He now is the founder and owner of Le Reseau, a company specializing in security-related issues for UNIX, OpenVMS and Windows NT, and the application of Linux in corporate environments.