At work, I’ve been asked how to spoof an IP address, for a variety of reasons. The teams I usually work with deal exclusively with Web Services, Web Applications, and C#. They’re very competent developers/engineers and occasionally some of the testing that they do makes the development teams think that spoofing is required. This got me thinking that perhaps there are a number of other folks who have this same question and a quick search & review of the topics on stack overflow confirmed that I was right.
Stack Overflow is great for getting a very quick, answer to a specific problem, but often not so great about education and explaining why things are hard. IP Spoofing is a security concept and something that every security person should be aware of how it really works. The teams that I work with are most concerned with making HTTP requests & responses to specific web applications. As I said before, they’re very good at it. With the advent of more high level languages, APIs and libraries to abstract all of this away, how do we really spoof an IP address to begin with?
OSI Layer Model
A key component to understanding how to actually spoof an IP address is one needs to have a vague understanding of the Open Source Interconnection 7 layer model. This is a model that describes how a computer takes a request from a web browser or some other application at the application layer and goes out, to the network to fetch the data and bring it back. It’s important to understand that approximately 98% of all active web development going on today takes place at the application layer or layer 7 of the OSI model. Your web browser, ftp client, mail client, or custom application all live at layer 7 in the model, for the most part and they’re all going to make a high level request over one protocol or another. In C#, typically they are used for making such high level requests.
The OSI layer model looks like this:
When a request for a web page such as
security.howellsonline.ca my application (Web Browser) in this case packages that application up, and sends it on down to layer 6,5,4,3. Layers 4 & 3 are where the interesting things start to happen, that domain name is turned into an IP address, packets are formed, containing the type of packet, the destination IP and the source IP, so I can get the data back. My pay load (Http Get request) in this instance is addressed, control measures on the flow are put into place and the information is pushed down to layers 2 & 1 which are the low level network (out onto the internet) and the physical network (cables, switches, routers) and with any luck in not to much time, I’ll get some return information that will start to work its way back up the OSI stack containing my return payload which is the content you’re reading right now.
The good news for web application developers and most application developers that want to make web requests is that there is no need to really care what each and every layer of the OSI stack does and there is therefore a simplified version of the OSI model, commonly known as the TCP/IP stack.
The TCP/IP stack looks like this:
You can clearly see that the TCP/IP stack is just a simplified version of the world where the TCP/IP stack considers the first 3 layers of the OSI model to be the application layer, and the last 4 to be data control and flow.
To really understand this, and it’s critical that we do before proceeding any further, let's consider a mapping of the TCP/IP stack to the OSI 7 layers.
Looking at these 3 different views of the networking world, it should be apparent that if we make a high level request for a resource, it’s really too late to try to enforce any kind of spoofing once I’ve asked for that high level request to be sent. The reason is, once I send a high level request, libraries, other applications and drivers take over at lower 4 levels of the TCP/IP stack and figure out all the hard work for me, and I am left with little chance to jump in and try and influence the process. A high level request interacts with the high levels of the stacks and doesn’t leave me much of a chance to mess with anything.
Spoofing an IP
We should now have a clear understanding that if we truly want to spoof an IP address, we have to get our hands a little dirty and we cannot work any higher than layer 4 of the OSI model. In fact, to truly be effective at spoofing an IP address, we need to work just about the network layer and really work within layers 4 & 3 of the OSI model. In order to do this, we effectively need to use a low level language like C++.
This is a code snippet and there are a few more things required, to make this program work, however this is what is going on.
1. int sd;
2. unsigned long dest_addr;
3. unsigned long src_addr;
4. src_addr = inet_addr(argv);
5. dest_addr = inet_addr(argv);
6. sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
7. setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
8. setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
9. int pack_size = sizeof(struct iphdr) + sizeof(struct icmphdr) + pay_load_size;
10. char* packet = (char*)malloc(pack_size);
11. ip->version = 4;
12. ip->ihl = 5;
13. ip->tos = 0;
15. ip->id = rand();
17. ip->ttl = 255;
18. ip->protocol= IPPROTO_ICMP;
21. icmp->type= ICMP_ECHO;
26. std::memset(packet + sizeof(struct iphdr) + sizeof(struct icmphdr), rand() % 255, pay_load_size);
27. sendto(sd, packet, pack_size,0, (struct sockaddr*)&servaddr, sizeof(servaddr));
Lines 1 – 8. Are basically getting the source address and the destination address, and setting up a socket to send the information through. The information that is going to be sent is the raw packet that I am going to construct later. Lines 6 -8 are basically creating a raw socket and telling the operating system what to do with it. Here I am saying, create the raw socket and basically don’t invoke any of your normal processing at layer 3, I am going to do everything. By virtue of creating a raw socket and then telling the socket I am going to provide all the IP headers, I am working at layers 4 (socket) and layers 3 (packet information). Lines 9 & 10 basically go about creating a packet for me.
Graphically a packet looks like:
Everything you see in IP headers is normally computed by layer 3, when issuing a high level request, however, on lines 6 – 8 when I said create a raw packet and said that I would be supplying the IP headers, I am telling the socket I know how to do this, and I will be replacing layer 3 essentially. Then that’s what I do on lines 11 – 25. I basically have a pointer to all those memory blocks represented graphically in the packet, and I am populating them with values. Looking at the image, I tell the packet that it’s going to be an ICMP packet, and an ICMP ECHO Packet [Different types of ICMP packets are out of scope]. However, because I mention it's going to be an ICMP packet, I also have to provide the ICMP headers.
In the code segment, pay particular attention to 19 & 20. This is where I populate the source address (the sender) & the destination address (where I want the packet to go). Since those are read in from the command line, on lines 4 & 5. I can put any value I want in for the sender, and for the destination. The routers will read these fields in the packet to determine how and where to send the data. As well the receiving end, will use the source address to create a return packet with the source in the destination. Lines 19 & 20 are where I successfully spoof the source IP address. Line 26 is where I construct the pay load for the packet, in this case, I am filling my packets with random numeric data, the size of a byte. Line 27. Is where the packet gets passed from layer 3 onto layer 2 and then out the door to layer 1 and onto the network successfully spoofing the source address. Because I’ve successfully spoof’d the source address I’ll never get a response back, to me personally.
Not Windows Programming
If at this point you’ve said wait a minute, this doesn’t look like how I create sockets doing TCP/IP programming on Windows you’d be 100% correct. The reason for this is because Windows at about Windows 7 and later has stopped allowing developers/engineers to create sockets with raw socket access for security reasons. Therefore this code was written using Kali Linux to demonstrate this exploit and how to effectively enable IP address spoofing.
The Full Attack
Let's walk through the program in fully operation now. Let's examine the attacker machine (That’s going to send the packets). Notice the IP address of the VMNet1 interface, this ip address is
192.168.67.1 This is the address the victim should see the attack coming from.
The victim machine looks like, therefore the attacker is going to attack ip address
The attack gets launched using the spoofer program, that the code snippet was taken from, notice what I am supplying for the source ip address
22.214.171.124. This is the address that is going to get populated in the packet header source address shown above. As we see, the victim’s IP address is the destination address.
When I run wireshark on the victim’s machine, I can very clearly see. ICMP ECHO Ping packets attacking the victim, notice the source address that wireshark is displaying that it’s displaying the
126.96.36.199 address NOT
192.168.67.1 the true address sending the packets. In this case, the interface
192.168.67.1 will never receive a reply. However I really don’t care, I’ve successfully spoofed my address and been successful in my attack.
When I analyze an actual data packet, again I can clearly see that the this packet originated at IP address
188.8.131.52, however we clearly know that’s not the correct address, and the IP address has been successfully spoofed.