防御
--------
当然,最好的防御是首先防止出现入侵和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 0a
bcast..
# 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 0a
Y..
# 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 0a
16.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 0a
mping..
## 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 0a
casts..
# 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 [...]]-PSend "png" command-SSend "shi" command-DSend "d1e" command (default)-p password(default:"l44adsl")
-f from_host(default:$hostname)-s src_port(default:random)-d dest_port(default:27444)-l ipfileSend to IP addresses in ipfile-i interface Set sending interface (default:eth0)-vVerbose-h This help
" 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
" 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 Magazine
Volume 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