下一页 1 2
简介 trinoo [03] -------------------------------------------------------------------------- 本机并未使用telnetd支持远程登录,而是SSH。入侵者在/etc/inetd.conf中增加了
分布式拒绝服务攻击工具mstream是基于stream2.c源码的。目前为止有七种公认的分布式拒绝服务攻击
Tribe Flood Network (TFN) [04]
Tribe Flood Network 2000 (tfn2k) [06]
stacheldraht/stacheldrahtV4 [05]
stacheldraht v2.666
shaft [07]
mstream
与其它DDoS工具相比,mstream显得粗糙多了。逆向工程还原出的C代码表明mstream尚处在早期开发阶段,含有大量的BUGs以及未完成的特性。然而由于stream/stream2攻击本身所具有的威力,即使参与的攻击机只有几台,也足以对victim(以及agent)所在网络产生极大影响。
mstream的源代码于2000年4月29日被人匿名发布到vuln-dev@securityfocus.com以及BugTraq邮件列表上,因此本文做少许修正,希望紧急事件响应小组、厂商花点时间提出自己的响应办法。仍存留在本文中的错误可能正是这次匆忙而就的修正所致。
提醒读者的是,对源代码的修改必将导致与本文分析细节不相符,比如提示、口令、命令、TCP/UDP端口号、所支持的攻击方式、签名、特性等等。事实上,外面广为流传的代码的通讯端口已与本文分析中的不同。
本文使用了CERT Distributed System Intruder Tools workshop于1999年11月所发布的术语标准。强烈建议先阅读如下链接以做背景知识
http://www.cert.org/reports/dsit_workshop.pdf
http://staff.washington.edu/dittrich/misc/ddos/
2000年4月下旬在某大学一台被入侵的Linux主机上发现了mstream agent,该机正以伪造的源IP对超过一打(12个)的目标主机进行flooding攻击。
这个子网的出口上应用了RFC 2267所定义的外出过滤规则(参考资源[13]),在32bits范围内伪造的源IP中,只有一小部分(匹配子网掩码的)能离开子网发送出去。然而,此时出口路由器(内侧有18个子网)停止响应。这意味着做外出过滤规则的路由设备本身将遭受攻击,尽管原来所定攻击目标只收到比攻击者预期要少得多的攻击报文。教训是,对于DDoS,简单的包过滤机制并不是一个快速有效的解决方案。我们已经提醒了路由厂商,希望他们能找出问题原因并修正之。
应用外出过滤规则后被拒绝外出的攻击报文无法到达下一跳路由器,下一跳路由器感受不到攻击。这意味着基于IDS的边界路由器、DMZ上的IDS或者ISP方的监视设备无法确认攻击发生。除非你正在监视路由器本身,而用户抱怨并暗示攻击来自你的子网。
这也使Sniffer抓包分析更加困难,只能在应用外出过滤规则的路由器内侧才能抓到所有包。
2000年2月上旬一家电子商务网站遭受攻击,至今为止他们还不知道对方使用何种攻击工具,只知道他们的路由器崩溃了,每次都依赖于他们的上级路由器阻断攻击、恢复通讯。法律部门在缺乏证据的情况下无法介入,他们不能认定这是DoS、DDoS攻击而非路由器、浏览器自身技术故障。针对Yahoo!的攻击描述在Packetstormsecurity找到(参考资源[11]),并没有更多其它可用信息。
1999年trinoo、TFN和stacheldraht伴随着大量自动入侵行为,mstream则处在代码开发的早期阶段,通常是手工入侵、安装(包括handler和agent),并用一个略微改动后的Linux rootkit version 4 [10]保护自己。
附录D介绍了一次针对agent的入侵和踪迹隐藏。附录E介绍了一次针对handler的入侵和踪迹隐藏。
☆ mstream network: client(s)-->handler(s)-->agent(s)-->victim(s)
与trinoo和shaft一样,mstream network由一个或多个handlers(master.c)以及大量的agents(server.c)组成。Attacker到handler之间的通讯是未加密的TCP传输,handler到agent之间的通讯是未加密的UDP传输。整个结构看上去像这个样子
--------------------------------------------------------------------------
+----------+ +----------+
| attacker | | attacker |
+----------+ +----------+
| |
. . . --+------+---------------+------+----------------+-- . . .
| | |
| | |
+-----------+ +-----------+ +-----------+
| handler | | handler | | handler |
+-----------+ +-----------+ +-----------+
| | |
| | |
. . . ---+------+-----+------------+---+--------+------------+-+-- . . .
| | | | |
| | | | |
+-------+ +-------+ +-------+ +-------+ +-------+
| agent | | agent | | agent | | agent | | agent |
+-------+ +-------+ +-------+ +-------+ +-------+
图: mstream network
--------------------------------------------------------------------------
☆ 通讯
Attacker -> Handler(s) : 6723/tcp (in published source)
15104/tcp ("in the wild")
12754/tcp (in recovered source)
Agent -> Handler(s) : 9325/udp (in published source)
6838/udp ("in the wild")
Handler -> Agent(s) : 7983/udp (in published source)
10498/udp ("in the wild")
Attacker到Handler的远程控制是通过TCP连接完成的,端口号不定(很容易产生变体)。
Handler所等待的命令应该完整地位于单个TCP报文的数据区(PDU)中,而不是断续的字节流。这意味着不能使用"telnet"控制Handler,netcat [19]可以胜任。SecurityFocus [20]中的源代码并未包含这样的客户端工具。
Attacker到Handler的传输未做加密处理,尽管stacheldraht表明增加Blowfish block cipher并不困难。命令行靠空格分隔参数。
与trinoo类似,Handler(s)与Agent(s)之间的通讯通过UDP报文完成。Agents命令行靠斜杠('/')分隔参数,多项参数自身靠冒号(':')分隔。
我们所检查的代码中最多允许3个Attackers连接到一个Handler,或许这是一个保护性措施,也可能是个多余的访问限制。连接建立后,必须提交正确的口令,缺省值如下
Attacker -> Handler(s) : "sex" (in published source [20])
"N7%diApf!" (in recovered source)
如果口令不正确,所有目前已建立连接的用户被提醒有人正试图访问该Handler,然后关闭这个未通过验证的连接。如果口令正确,所有目前已建立连接的用户被提醒产生新的会话连接,通过验证的用户得到一个"> "提示符。
☆ Handler命令
Handler命令行至多由3个空格分隔的参数组成(argv[0] - argv[2])。
如果攻击者建立连接后420秒内未输入一条命令,连接终止。
Handler命令集如下
help
显示如下信息
Available commands:
stream stream attack !(进行stream攻击)
servers Prints all known servers.(显示所有已知servers/agents)
ping ping all servers.
who tells you the ips of the people logged in
mstream lets you stream more than one ip at a time
servers
显示当前所有已知Agents
who
显示当前已建立连接的用户
ping
确认Agents的活动状态。对所有已知Agents发送"ping",每收到一个"pong"回应就报告用户。
stream
针对单个主机攻击,seconds指定攻击持续时间。Handler将主机名解析成IP地址并发送命令"mstream/arg1:arg1/arg2"到所有Agents,这里arg1是victim目标IP地址,arg2是攻击持续时间。
mstream
针对多台主机攻击,seconds指定攻击持续时间。Handler发送命令"mstream/arg1/arg2"到所有Agents,这里arg1是冒号分隔的victim目标IP地址列表,arg2是攻击持续时间。
quit
终止Attacker到Handler的连接
☆ Agent命令
Handler到Agent的命令位于UDP报文的数据区(PDU)中,未做加密处理(尽管这很容易做到)。
目前仅有三条Agent命令。Agent命令行是一个靠斜杠("/")分隔参数的简单字符串。
ping
对发送该命令的IP响应以"pong"。
stream/IP/seconds
开始对指定IP进行攻击,seconds指定攻击持续时间。
mstream/IP1[:IP2[:IPN]]/seconds
开始对指定IP列表进行攻击,seconds指定攻击持续时间。
尽管Agent可以接受stream和mstream两种命令,但实际只有mstream命令用于Handler与Agent之间。"stream 192.168.0.100 10"将被转换成"mstream/192.168.0.100:192.168.0.100/10",然后发送到Agent。不清楚为何要这样处理,或许这只是表明mstream的开发过程快速而凌乱。
☆ 口令保护
Handler受口令保护,以防止其被任意接管。口令未做加密处理,仅仅是明文字符串
之间的比较。可以利用Sniffer获取口令明文。
这里应该再次提醒的是,mstream有一个特性是其它DDoS工具所不具有的,它会提醒
所有已建立连接的用户有新的连接试图建立,无论成功与否。
令人惊奇的是Handler与Agent之间无口令保护。
☆ 指纹
前面提到了,Handler(s)与Agent(s)之间的命令串是明文字符串,在通讯报文中可见。
对Agent使用strings命令可以看到这样一些明文字符串(为了节省显示空间做了处理)
--------------------------------------------------------------------------
ELF mstream
/lib/ld-linux.so.2 ping
GNU pong
__gmon_start__ fork
libc.so.6 init.c
random . . .
getpid server.c
perror strchr@@GLIBC_2.0
getuid packet
malloc getpid@@GLIBC_2.0
recvfrom _DYNAMIC
socket _etext
bind __register_frame_info@@GLIBC_2.0
inet_addr recvfrom@@GLIBC_2.0
__deregister_frame_info _fp_hw
setsockopt perror@@GLIBC_2.0
rand fork@@GLIBC_2.0
strncmp sock
strncpy cksum
sendto random@@GLIBC_2.0
strtok _init
fork malloc@@GLIBC_2.0
memset getppid@@GLIBC_2.0
srand sendto@@GLIBC_2.0
getppid __deregister_frame_info@@GLIBC_2.0
time setsockopt@@GLIBC_2.0
htons time@@GLIBC_2.0
exit _start
atoi forkbg
_IO_stdin_used strlen@@GLIBC_2.0
__libc_start_main stream
strlen strncmp@@GLIBC_2.0
strchr inet_addr@@GLIBC_2.0
__register_frame_info __bss_start
free main
GLIBC_2.0 __libc_start_main@@GLIBC_2.0
PTRh data_start
QVh0 bind@@GLIBC_2.0
Ph% getuid@@GLIBC_2.0
PhG _fini
WVS s_in
[^_ srand@@GLIBC_2.0
WVS nlstr
j(j exit@@GLIBC_2.0
j h atoi@@GLIBC_2.0
j(h _edata
j h in_cksum
j(h _GLOBAL_OFFSET_TABLE_
[^_ free@@GLIBC_2.0
131.247.208.191 _end
129.79.20.202 htons@@GLIBC_2.0
socket send2master
bind memset@@GLIBC_2.0
setsockopt strncpy@@GLIBC_2.0
newserver _IO_stdin_used
stream strtok@@GLIBC_2.0
__data_start __gmon_start__
socket@@GLIBC_2.0 rand@@GLIBC_2.0
--------------------------------------------------------------------------
对Handler使用strings命令可以看到这样一些明文字符串(做了处理)
--------------------------------------------------------------------------
% strings -n 3 master
socket stream
bind stream attack !
listen servers
setsockopt Prints all known servers.
fcntl ping
You're too idle ! ping all servers.
Connection from %s who
newserver tells you the ips of the people log
New server on %s. mstream
pong lets you stream more than one ip at
Got pong number %d from %s who
%s has disconnected (not auth'd): %s Currently Online:
Invalid password from %s. Socket number %d
Password accepted for connection fr [%s]
Lost connection to %s: %s ping
stream Pinging all servers.
Usage: stream mstream
Unable to resolve %s. Usage: mstream stream/%s/%s MStreaming %s for %s seconds.
Streaming %s for %s seconds. mstream/%s/%s
quit fork
%s has disconnected. Forked into background, pid %d
servers Caught SIGHUP, ignoring.
Server file doesn't exist, creating Caught SIGINT, ignoring.
The following ips are known servers Segmentation Violation, Exiting cle
help Caught unknown signal, This should
commands Available commands:
--------------------------------------------------------------------------
用lsof命令检查Agent,在这台主机上它名为"rpc.wall",Handler也用同样的名字
--------------------------------------------------------------------------
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
rpc.wall 588 root cwd DIR 3,2 1024 2 /
rpc.wall 588 root rtd DIR 3,2 1024 2 /
rpc.wall 588 root txt REG 3,3 17016 15765 /usr/bin/rpc.wall
rpc.wall 588 root mem REG 3,2 342206 30771 /lib/ld-2.1.1.so
rpc.wall 588 root mem REG 3,2 4016683 30789 /lib/libc-2.1.1.so
rpc.wall 588 root 0u CHR 5,1 4952 /dev/console
rpc.wall 588 root 1w FIFO 0,0 646 pipe
rpc.wall 588 root 2w FIFO 0,0 647 pipe
rpc.wall 588 root 3u IPv4 656 UDP *:10498
rpc.wall 588 root 4u IPv4 657 UDP *:1044
rpc.wall 588 root 5u IPv4 658 UDP *:1045
rpc.wall 588 root 6u raw 30219 00000000:00FF->00000000:0000 st=07
rpc.wall 588 root 7r FIFO 0,0 648 pipe
rpc.wall 588 root 8u raw 30241 00000000:00FF->00000000:0000 st=07
rpc.wall 588 root 9u CHR 5,1 4952 /dev/console
rpc.wall 588 root 10u IPv4 30244 UDP *:1051
rpc.wall 588 root 11u raw 30245 00000000:00FF->00000000:0000 st=07
rpc.wall 588 root 21w FIFO 0,0 648 pipe
--------------------------------------------------------------------------
server.c和master.c都有BUG,结果Agent多出一些raw socket、UDP socket(在这个例子中各多出两个),而Handler会多出一些打开的文件句柄以及UDP socket(Andrew Korty曾经检查到数百个)。毫无疑问,mstream处在早期开发阶段,所以这些签名并不可靠。
当一个Agent第一次启动时,它向编译时固化进二进制文件的缺省Handlers列表发送
"newserver"命令,用tcpdump可以看到如下内容
--------------------------------------------------------------------------
00:04:38.530000 192.168.0.20.1081 > 192.168.0.100.6838: udp 9
0x0000 4500 0025 ef75 0000 4011 098a c0a8 0014 E..%.u..@.......
0x0010 c0a8 0064 0439 1ab6 0011 2b63 6e65 7773 ...d.9....+cnews
0x0020 6572 7665 7200 0000 0000 0000 0000 erver.........
--------------------------------------------------------------------------
如果发现rootkit存在(Handler和Agent上都会使用),你不能相信标准操作系统命令的输出,比如进程、网络连接等等。所有的系统管理员都应该花点时间看看参考资源[10]以了解rootkit。
前面提到了,如果一个Agent在10498/UDP上收到一个UDP报文,其数据区包含字符串"ping",如果这个Agent此时没有处在攻击状态中,则响应一个UDP报文,目标端口6838/UDP,数据区包含字符串"pong"。下面是tcpdump的输出,结尾的0是tcpdump自己增加的,实际负载只有4个字节。
--------------------------------------------------------------------------
00:05:16.457239 192.168.0.100.65364 > 192.168.0.20.10498: udp 5
0x0000 4500 0021 f412 0000 4011 04f1 c0a8 0064 E..!....@......d
0x0010 c0a8 0014 ff54 2902 000d 6ce3 7069 6e67 .....T)...l.ping
0x0020 0a .
00:05:16.458214 192.168.0.20.1083 > 192.168.0.100.6838: udp 4
0x0000 4500 0020 ef8c 0000 4011 0978 c0a8 0014 E.......@..x....
0x0010 c0a8 0064 043b 1ab6 000c 8045 706f 6e67 ...d.;.....Epong
0x0020 0000 0000 0000 0000 0000 0000 0000 ..............
--------------------------------------------------------------------------
可以用ngrep [14]、snort [18](附录B介绍了snort规则)做签名匹配,或者用rid
[15](附录C有一个RID模板)搜索空闲(未做攻击)Agents。
# ngrep "p[oi]ng" udp port 6838 or udp port 10498
如果攻击者修改了源代码,这条ngrep命令所用端口也要修改。
攻击报文固定在40字节大小,或许是规避某些IDS的大包检测规则。
stream2.c对victim做TCP ACK Flooding,源IP随机化(用random()产生),源端口和
TCP序列号顺序递增。参看如下源代码
--------------------------------------------------------------------------
. . .
for ( i = 0; ; ++i )
{
cksum.pseudo.saddr = packet.ip.ip_src.s_addr = random();
++packet.ip.ip_id;
++packet.tcp.th_sport;
++packet.tcp.th_seq;
if ( !dstport )
{
s_in.sin_port = packet.tcp.th_dport = rand();
}
. . .
--------------------------------------------------------------------------
由于源IP随机化,伪造得到的点分十进制源IP可能出现某些字节为0的情况。
用tcpdump抓取攻击报文
--------------------------------------------------------------------------
01:39:24.701083 192.168.0.2.65527 > 192.168.0.20.10498: [bad udp cksum 3100!]
udp 24 (ttl 64, id 886)
0x0000 4500 0034 0376 0000 4011 f5dc c0a8 0002 E..4.v..@.......
0x0010 c0a8 0014 fff7 2902 0020 556c 7374 7265 ......)...Ulstre
0x0020 616d 2f31 3932 2e31 3638 2e30 2e31 3030 am/192.168.0.100
0x0030 2f31 300a /10.
01:40:10.132724 192.168.0.2.65526 > 192.168.0.20.10498: [bad udp cksum 3100!]
udp 24 (ttl 64, id 930)
0x0000 4500 0034 03a2 0000 4011 f5b0 c0a8 0002 E..4....@.......
0x0010 c0a8 0014 fff6 2902 0020 556d 7374 7265 ......)...Umstre
0x0020 616d 2f31 3932 2e31 3638 2e30 2e31 3030 am/192.168.0.100
0x0030 2f31 300a /10.
01:41:23.674796 192.168.0.2.65525 > 192.168.0.20.10498: [bad udp cksum 4a00!]
udp 49 (ttl 64, id 1031)
0x0000 4500 004d 0407 0000 4011 f532 c0a8 0002 E..M....@..2....
0x0010 c0a8 0014 fff5 2902 0039 a9b4 6d73 7472 ......)..9..mstr
0x0020 6561 6d2f 3139 322e 3136 382e 302e 313a eam/192.168.0.1:
0x0030 3139 322e 3136 382e 302e 3130 303a 3139 192.168.0.100:19
0x0040 322e 3136 382e 302e 322f 3130 0a 2.168.0.2/10.
01:41:23.675771 arp who-has 192.168.0.1 tell 192.168.0.20
0x0000 0001 0800 0604 0001 0010 5a99 6544 c0a8 ..........Z.eD..
0x0010 0014 0000 0000 0000 c0a8 0001 0000 0000 ................
0x0020 0000 0000 0000 0000 0000 0000 0000 ..............
01:41:23.675772 arp who-has 192.168.0.100 tell 192.168.0.20
0x0000 0001 0800 0604 0001 0010 5a99 6544 c0a8 ..........Z.eD..
0x0010 0014 0000 0000 0000 c0a8 0064 0000 0000 ...........d....
0x0020 0000 0000 0000 0000 0000 0000 0000 ..............
01:41:23.675773 77.172.43.85.38444 > 192.168.0.2.26296: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 50237)
0x0000 4508 0028 c43d 0000 ff06 bdde 4dac 2b55 E..(.=......M.+U
0x0010 c0a8 0002 962c 66b8 ea97 d237 0000 0000 .....,f....7....
0x0020 5010 4000 7c74 0000 0000 0000 0000 P.@.|t........
01:41:23.675774 88.148.222.45.39212 > 192.168.0.2.10342: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 51005)
0x0000 4508 0028 c73d 0000 ff06 fd1d 5894 de2d E..(.=......X..-
0x0010 c0a8 0002 992c 2866 ed97 d237 0000 0000 .....,(f...7....
0x0020 5010 4000 f705 0000 0000 0000 0000 P.@...........
01:41:23.675775 0.18.219.113.39980 > 192.168.0.2.41622: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 51773)
0x0000 4508 0028 ca3d 0000 ff06 555c 0012 db71 E..(.=....U\...q
0x0010 c0a8 0002 9c2c a296 f097 d237 0000 0000 .....,.....7....
0x0020 5010 4000 d213 0000 0000 0000 0000 P.@...........
01:41:23.675776 121.161.140.109.40748 > 192.168.0.2.16749: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 52541)
0x0000 4508 0028 cd3d 0000 ff06 27d1 79a1 8c6d E..(.=....'.y..m
0x0010 c0a8 0002 9f2c 416d f397 d237 0000 0000 .....,Am...7....
0x0020 5010 4000 02b2 0000 0000 0000 0000 P.@...........
01:41:23.675777 79.238.213.72.41516 > 192.168.0.2.46276: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 53309)
0x0000 4508 0028 d03d 0000 ff06 05a9 4fee d548 E..(.=......O..H
0x0010 c0a8 0002 a22c b4c4 f697 d237 0000 0000 .....,.....7....
0x0020 5010 4000 6a32 0000 0000 0000 0000 P.@.j2........
01:41:23.675778 104.24.203.64.42284 > 192.168.0.2.61623: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 54077)
0x0000 4508 0028 d33d 0000 ff06 f486 6818 cb40 E..(.=......h..@
0x0010 c0a8 0002 a52c f0b7 f997 d237 0000 0000 .....,.....7....
0x0020 5010 4000 1a1d 0000 0000 0000 0000 P.@...........
01:41:23.675779 37.60.73.50.43052 > 192.168.0.2.51311: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 54845)
0x0000 4508 0028 d63d 0000 ff06 b671 253c 4932 E..(.=.....q%0x0010 c0a8 0002 a82c c86f fc97 d237 0000 0000 .....,.o...7....
0x0020 5010 4000 0150 0000 0000 0000 0000 P.@..P........
01:41:23.675780 142.14.73.40.43820 > 192.168.0.2.8979: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 55613)
0x0000 4508 0028 d93d 0000 ff06 4aa9 8e0e 4928 E..(.=....J...I(
0x0010 c0a8 0002 ab2c 2313 ff97 d237 0000 0000 .....,#....7....
0x0020 5010 4000 37e4 0000 0000 0000 0000 P.@.7.........
01:41:23.676748 144.19.212.69.44588 > 192.168.0.2.51668: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 56381)
0x0000 4508 0028 dc3d 0000 ff06 ba86 9013 d445 E..(.=.........E
0x0010 c0a8 0002 ae2c c9d4 0298 d237 0000 0000 .....,.....7....
0x0020 5010 4000 fdff 0000 0000 0000 0000 P.@...........
01:41:23.676749 155.176.45.2.45356 > 192.168.0.2.32793: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 57149)
0x0000 4508 0028 df3d 0000 ff06 532d 9bb0 2d02 E..(.=....S-..-.
0x0010 c0a8 0002 b12c 8019 0598 d237 0000 0000 .....,.....7....
0x0020 5010 4000 dd61 0000 0000 0000 0000 P.@..a........
01:41:23.676750 10.98.211.13.46124 > 192.168.0.2.1995: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 57917)
0x0000 4508 0028 e23d 0000 ff06 3b70 0a62 d30d E..(.=....;p.b..
0x0010 c0a8 0002 b42c 07cb 0898 d237 0000 0000 .....,.....7....
0x0020 5010 4000 3af3 0000 0000 0000 0000 P.@.:.........
01:41:23.676751 214.235.187.89.46892 > 192.168.0.2.14172: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 58685)
0x0000 4508 0028 e53d 0000 ff06 839a d6eb bb59 E..(.=.........Y
0x0010 c0a8 0002 b72c 375c 0b98 d237 0000 0000 .....,7\...7....
0x0020 5010 4000 508c 0000 0000 0000 0000 P.@.P.........
01:41:23.676752 90.193.127.8.47660 > 192.168.0.2.64812: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 59453)
0x0000 4508 0028 e83d 0000 ff06 3916 5ac1 7f08 E..(.=....9.Z...
0x0010 c0a8 0002 ba2c fd2c 0e98 d237 0000 0000 .....,.,...7....
0x0020 5010 4000 3d37 0000 0000 0000 0000 P.@.=7........
01:41:23.676753 160.176.42.60.48428 > 192.168.0.2.17432: . [tcp sum ok]
ack 0 win 16384 [tos 0x8] (ttl 255, id 60221)
0x0000 4508 0028 eb3d 0000 ff06 44f3 a0b0 2a3c E..(.=....D...*<
0x0010 c0a8 0002 bd2c 4418 1198 d237 0000 0000 .....,D....7....
0x0020 5010 4000 ff28 0000 0000 0000 0000 P.@..(........
--------------------------------------------------------------------------
对Cisco Net Flows产生的日志使用如下命令(过滤点分十进制中含有0的IP地址)可以
发觉攻击的存在
--------------------------------------------------------------------------
% grep "[ \.]0[ \.(]" ddos-000415
Apr 15 04:12:08 tcp 82.0.151.5(29497) -> 192.168.10.5(27072), 1 packet
Apr 15 04:12:18 tcp 207.0.149.32(21893) -> 192.168.10.5(3913), 1 packet
Apr 15 04:12:33 tcp 0.147.151.82(10473) -> 10.4.152.237(2810), 1 packet
Apr 15 04:13:39 tcp 60.0.33.36(41079) -> 10.4.152.237(31754), 1 packet
Apr 15 04:14:03 tcp 103.140.148.0(4247) -> 10.4.152.237(29689), 1 packet
Apr 15 04:14:15 tcp 214.1.99.0(46714) -> 10.4.152.237(22524), 1 packet
Apr 15 04:15:11 tcp 10.148.60.0(12276) -> 192.168.10.5(31122), 1 packet
Apr 15 04:15:20 tcp 0.112.67.108(4550) -> 192.168.10.5(63787), 1 packet
Apr 15 04:15:33 tcp 13.0.16.2(39092) -> 10.4.152.237(57998), 1 packet
. . .
Apr 15 06:45:24 tcp 18.167.171.0(54104) -> 10.200.5.8(32779), 1 packet
Apr 15 06:45:52 tcp 0.23.15.38(45621) -> 10.200.5.8(20780), 1 packet
Apr 15 06:46:14 tcp 0.12.109.77(38670) -> 10.200.5.8(47776), 1 packet
Apr 15 07:19:12 tcp 199.120.0.72(64912) -> 10.4.152.237(45151), 1 packet
Apr 15 07:27:37 tcp 0.28.232.21(52533) -> 10.4.152.237(338), 1 packet
Apr 15 07:28:13 tcp 99.61.233.0(20951) -> 10.4.152.237(58427), 1 packet
Apr 15 07:31:23 tcp 195.0.3.111(17193) -> 10.4.152.237(14601), 1 packet
Apr 15 07:32:19 tcp 61.108.245.0(24309) -> 10.4.152.237(32809), 1 packet
--------------------------------------------------------------------------
应该提醒的是某些伪造得到的源IP是广播地址、组播地址、子网地址,这将产生一些
其它问题(参考资源[12])。
分析stream2.c的源代码,IP、TCP层的很多头部信息被随机化了,但还是有一些静态
值
--------------------------------------------------------------------------
packet.ip.ip_id = rand();
. . .
packet.tcp.th_win = htons(16384);
. . .
packet.tcp.th_seq = random();
. . .
packet.tcp.th_sport = rand();
packet.tcp.th_dport = rand();
. . .
while ( time( 0 ) <= endtime )
{
if ( floodtype != 0 )
{
i = 0;
/*
* until list exhausted
*/
while ( arg4[i] != NULL )
{
/*
* valid ip
*/
if ( strchr( arg4[i], '.' ) != NULL )
{
packet.ip.ip_dst.s_addr = inet_addr(arg4[i]);
cksum.pseudo.daddr = inet_addr(arg4[i]);
s_sin.sin_addr.s_addr = inet_addr(arg4[i]);
cksum.pseudo.saddr = packet.ip.ip_src.s_addr = random();
packet.ip.ip_id++;
packet.tcp.th_sport++;
packet.tcp.th_seq++;
s_in.sin_port = packet.tcp.th_dport = rand();
. . .
}
}
}
}
--------------------------------------------------------------------------
☆ 防御
我们没有时间完成这部分内容,任何针对stream/stream2 [12]或者其它DDoS工具
[08]的防御讨论都可一试。最后,看在上帝的份上,网管、系管们做好自身的安全防
卫工作吧,我晕倒。
☆ 弱点
由于Attacker、Handler、Agent之间的通讯未加密,很容易被Sniffer、Hijack等等。
Agent(s)不对命令来源做任何验证,我们可以利用"ping/pong"特性找出那些当前未
做攻击的Agent(s)。
"pong"是Agent到Handler的唯一响应,"newserver"是Agent第一次启动时发给
Handler的。附录D介绍了Agent的安装,每次系统重启都会启动Agent。这意味着在系
统重启时可以抓到"newserver"包,我们不推荐这样去鉴别Agent的存在,至少不该是
首选动作。参看附录D、附录E。
Agent接收到一个格式错误的命令串(比如"stream foo bar")时,将发生
segmentation fault,导致Agent(s)不可用,但是很可能在系统重启时恢复工作。
向Agent发送太多命令导致打开的文件句柄过多而最终停止响应。
Agent进程是单线程的,意味着在攻击中它无法处理来自Handler的命令,一旦攻击开
始,Agent将失去控制。
Agent工作在多种flood攻击模式下时,攻击列表中的所有主机遭受同样时间长度的攻
击以及同样类型的攻击(比如ICMP主机不可达、TCP RST)。
☆ 可能的修正
1) Handler上针对到自己的连接请求做源端口过滤
2) 在Handler与Agent之间增加验证机制
3) 报文大小可选
4) 允许指定flood packets的TCP标志(ACK、RST、NUL、random、whatever)
5) Attacker与Handler之间的通讯加密
6) 增加内置命令
☆ 附录B - 检测mstream的snort规则
alert UDP any any -> any 6838 (msg: "IDS100/ddos-mstream-agent-to-handler"; content: "newserver"; )
alert UDP any any -> any 10498 (msg: "IDS101/ddos-mstream-handler-to-agent"; content: "stream/"; )
alert UDP any any -> any 10498 (msg: "IDS102/ddos-mstream-handler-ping-to-agent" ; content: "ping";)
alert UDP any any -> any 10498 (msg: "IDS103/ddos-mstream-agent-pong-to-handler" ; content: "pong";)
alert TCP any any -> any 12754 (msg: "IDS109/ddos-mstream-client-to-handler"; flags: S;)
alert TCP any 12754 -> any any (msg: "IDS110/ddos-mstream-handler-to-client"; content: ">"; flags: AP;)
alert TCP any any -> any 15104 (msg: "IDS111/ddos-mstream-client-to-handler"; flags: S;)
alert TCP any 15104 -> any any (msg: "IDS112/ddos-mstream-handler-to-client"; content: ">"; flags: AP;)
☆ 附录C - 检测mstream的RID模板
start mstream-wild
send udp dport=10498 data="ping"
recv udp dport=6838 data="pong" nmatch=2
end mstream-wild
start mstream-published
send udp dport=7983 data="ping"
recv udp dport=9325 data="pong" nmatch=2
end mstream-published
scz注: 这里错误地使用了减号'-',证明这个模板是未经验证的
☆ 附录D - 最初的Agent系统的入侵和踪迹隐藏
通过检查Agent系统、询问管理员,确认发生过两次独立的入侵。第一个在2000年3月
31之前,/etc/passwd中留下了"inertia"帐号,管理员于4月1号删除了该帐号。上载
安装rootkit (lrk4)和DDoS Agent ("rpc.wall")是在4月13号16:02(这里提及的所有
时间,除非特别声明,均为美国/太平洋时间或GMT-0700时间),留有ADM named攻击
的痕迹,4月15号05:55还登录了一次。系统日志被删除、擦除过,所以无法根据日志
判断发生过什么。
Dan Farmer和Wietse Venema提供过一个"Coroner's Toolkit [16]",利用其中的
"mactime"还是可以看到入侵者的某些行为。下列输出中的年份100显然是Y2K问题。
--------------------------------------------------------------------------
Apr 13 100 16:02:42 12060 .aa -rwxr-xr-x root/www root /bin/chown
12660 m.m -r-sr-xr-x root/www bin /bin/login
Apr 13 100 16:02:43 2048 mcmc drwxr-xr-x root/www root /bin
12660 cc -r-sr-xr-x root/www bin /bin/login
168748 .a. -rwxr-xr-x root/www root /usr/bin/as
64796 .a. -rwxr-xr-x root/www root /usr/bin/egcs
64796 .a. -rwxr-xr-x root/www root /usr/bin/gcc
64796 .a. -rwxr-xr-x root/www root /usr/bin/i386-redhat-linux-gcc
168496 .a. -rwxr-xr-x root/www root /usr/bin/ld
12656 m.c -rws--x--x root/www root /usr/bin/old
12656 m.c -r-xr-xr-x root/www bin /usr/bin/xstat
2315 .a. -rw-r--r-- root/www root /usr/include/_G_config.h
1313 .a. -rw-r--r-- root/www root /usr/include/alloca.h
4090 .a. -rw-r--r-- root/www root /usr/include/arpa/inet.h
3451 .a. -rw-r--r-- root/www root /usr/include/bits/byteswap.h
13327 .a. -rw-r--r-- root/www root /usr/include/bits/confname.h
168 .a. -rw-r--r-- root/www root /usr/include/bits/endian.h
2283 .a. -rw-r--r-- root/www root /usr/include/bits/errno.h
5107 .a. -rw-r--r-- root/www root /usr/include/bits/fcntl.h
4647 .a. -rw-r--r-- root/www root /usr/include/bits/in.h
3406 .a. -rw-r--r-- root/www root /usr/include/bits/posix_opt.h
2842 .a. -rw-r--r-- root/www root /usr/include/bits/select.h
4673 .a. -rw-r--r-- root/www root /usr/include/bits/sigset.h
1716 .a. -rw-r--r-- root/www root /usr/include/bits/sockaddr.h
9033 .a. -rw-r--r-- root/www root /usr/include/bits/socket.h
1297 .a. -rw-r--r-- root/www root /usr/include/bits/stdio_lim.h
2015 .a. -rw-r--r-- root/www root /usr/include/bits/time.h
4673 .a. -rw-r--r-- root/www root /usr/include/bits/types.h
1781 .a. -rw-r--r-- root/www root /usr/include/bits/uio.h
1798 .a. -rw-r--r-- root/www root /usr/include/endian.h
2481 .a. -rw-r--r-- root/www root /usr/include/errno.h
4579 .a. -rw-r--r-- root/www root /usr/include/fcntl.h
9433 .a. -rw-r--r-- root/www root /usr/include/features.h
5861 .a. -rw-r--r-- root/www root /usr/include/getopt.h
973 .a. -rw-r--r-- root/www root /usr/include/gnu/stubs.h
10291 .a. -rw-r--r-- root/www root /usr/include/libio.h
17327 .a. -rw-r--r-- root/www root /usr/include/netdb.h
10779 .a. -rw-r--r-- root/www root /usr/include/netinet/in.h
1591 .a. -rw-r--r-- root/www root /usr/include/netinet/in_systm.h
9086 .a. -rw-r--r-- root/www root /usr/include/netinet/ip.h
4855 .a. -rw-r--r-- root/www root /usr/include/netinet/tcp.h
2550 .a. -rw-r--r-- root/www root /usr/include/rpc/netdb.h
6467 .a. -rw-r--r-- root/www root /usr/include/stdint.h
20816 .a. -rw-r--r-- root/www root /usr/include/stdio.h
27654 .a. -rw-r--r-- root/www root /usr/include/stdlib.h
13245 .a. -rw-r--r-- root/www root /usr/include/string.h
2104 .a. -rw-r--r-- root/www root /usr/include/strings.h
4932 .a. -rw-r--r-- root/www root /usr/include/sys/cdefs.h
3359 .a. -rw-r--r-- root/www root /usr/include/sys/select.h
7996 .a. -rw-r--r-- root/www root /usr/include/sys/socket.h
1577 .a. -rw-r--r-- root/www root /usr/include/sys/sysmacros.h
5337 .a. -rw-r--r-- root/www root /usr/include/sys/time.h
5299 .a. -rw-r--r-- root/www root /usr/include/sys/types.h
1907 .a. -rw-r--r-- root/www root /usr/include/sys/uio.h
9314 .a. -rw-r--r-- root/www root /usr/include/time.h
36708 .a. -rw-r--r-- root/www root /usr/include/unistd.h
874 .a. -rw-r--r-- root/www root /usr/lib/crtn.o
1446620 .a. -rwxr-xr-x root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cc1
46816 .a. -rwxr-xr-x root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/collect2
88444 .a. -rwxr-xr-x root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cpp
1424 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtend.o
5794 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stdarg.h
9834 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/include/stddef.h
770000 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/libgcc.a
1957 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs
178 .a. -rw-r--r-- root/www root /usr/lib/libc.so
69638 .a. -rw-r--r-- root/www root /usr/lib/libc_nonshared.a
6162 .a. -rw-r--r-- 1046 squid /usr/src/linux/include/asm-i386/errno.h
1492 .a. -rw-r--r-- 1046 squid /usr/src/linux/include/asm-i386/socket.h
277 .a. -rw-r--r-- 1046 squid /usr/src/linux/include/asm-i386/sockios.h
305 .a. -rw-r--r-- 1046 squid /usr/src/linux/include/linux/errno.h
Apr 13 100 16:02:44 702 mcmc -rwxr-xr-x root/www root /etc/rc.d/rc.local
1024 mcmc drwxr-xr-x root/www root /root/.ncftp
9 mcmc lrwxrwxrwx root/www root /root/.ncftp/history
9 mcmc lrwxrwxrwx root/www root /root/.ncftp/log
9 mcmc lrwxrwxrwx root/www root /root/.ncftp/trace
29696 m.c drwxr-xr-x root/www root /usr/bin
17016 m.c -rwxr-xr-x root/www root /usr/bin/rpc.wall
8460 .a. -rw-r--r-- root/www root /usr/lib/crt1.o
1124 .a. -rw-r--r-- root/www root /usr/lib/crti.o
1892 .a. -rw-r--r-- root/www root /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtbegin.o
. . .
Apr 15 100 05:55:09 1024 mcmc drwxr-xr-x root/www root /var/named
1024 mcmc drwxr-xr-x root/www root /var/named/ADMROCKS
Apr 15 100 05:56:19 20437 .a. -rwxr-xr-x root/www root /usr/sbin/tcpd
Apr 15 100 05:56:20 34 .aa -rw-r--r-- root/www root /usr/libexec/awk/addy.awk
35628 .a. -rwxr-xr-x root/www root /usr/sbin/in.telnetd
Apr 15 100 05:56:26 159576 .a. -rwxr-xr-x root/www root /usr/bin/pico
975 .a. -rw-r--r-- root/www root /usr/share/terminfo/v/vt200
975 .a. -rw-r--r-- root/www root /usr/share/terminfo/v/vt220
--------------------------------------------------------------------------
从这个输出中可以观察到如下信息
o 2000年4月13号16:02创建/bin/login、运行/bin/chown
o 与此同时,运行gcc/egcs进行编译,创建了/bin/old和/bin/xstat。.h文件的
Access times表明被编译的程序使用了socket
o 接下来/etc/rc.d/rc.local被修改,在最后增加了一行"/usr/bin/rpc.wall",于
是每次重启系统时都会自动启动Agent。ncftp日志文件被修改(先删除,然后符号
链接到/dev/null以阻止ncftp文件传输日志产生)
o 程序/usr/bin/rpc.wall被修改,C运行时库被访问过,这意味着rpc.wall运行过。
o 4月15号05:55,似乎有一次针对本机的ADM named远程缓冲区溢出攻击,然后访问
tcpd wrapped service激活in.telnetd。rootkit的配置文件
/usr/libexec/awk/addy.awk也被访问过。我们不清楚这是否仅仅碰巧是第三次入
侵企图。
o 6秒后/usr/bin/pico被运行,vt200终端类型。既然被安装了特洛伊木马的login包
含"vt200"字符串,可以确认远程root shell后门至少两天前就安装好了。
管理员只删除了/etc/passwd中的"inertia"帐号,并未删除/etc/shadow中的相应内容
inertia:iUCNir1cd8pI2:::::::
--------------------------------------------------------------------------
不到1秒就破解出这个口令"hi"
用strings命令观察/bin/login,带有典型的特洛伊木马特征,一个非标准命令(这里
是/usr/bin/xstat)和一个嵌入式终端类型(vt200)用于激活远程root shell
--------------------------------------------------------------------------
. . .
login
/bin/sh
/usr/bin/xstat
TERM
bcshjvmudzwxftejk
vt200
%s=%s
init.c
. . .
--------------------------------------------------------------------------
用strings命令观察/bin/ls和/bin/ps,显示rootkit配置文件分别是
/usr/libexec/awk/files.awk和/usr/libexec/awk/ps.awk。另一个配置文件是前面
提到的/usr/libexec/awk/addy.awk。
一个有用的窍门在于标准Linux rootkit编译时(由Makefile决定)保留了调试信息
--------------------------------------------------------------------------
. . .
ls.c
/home/XXXXX/stuff/lrk4/fileutils-3.13/src/
gcc2_compiled.
int:t1=r1;-2147483648;2147483647;
char:t2=r2;0;127;
. . .
--------------------------------------------------------------------------
如下内容
--------------------------------------------------------------------------
. . .
#finger stream tcp nowait root /usr/sbin/tcpd in.fingerd
#cfinger stream tcp nowait root /usr/sbin/tcpd in.cfingerd
#systat stream tcp nowait guest /usr/sbin/tcpd /bin/ps -auwwx
#netstat stream tcp nowait guest /usr/sbin/tcpd /bin/netstat -f inet
working stream tcp nowait root /usr/sbin/tcpd in.telnetd
. . .
--------------------------------------------------------------------------
然后在/etc/services中增加了如下内容
--------------------------------------------------------------------------
working 1120/tcp # Kerberos working daemon
--------------------------------------------------------------------------
用lsof可以看到这个侦听端口
--------------------------------------------------------------------------
inetd 353 root 4u IPv4 375 UDP *:talk
inetd 353 root 5u IPv4 376 UDP *:ntalk
inetd 353 root 6u IPv4 377 TCP *:working (LISTEN)
inetd 353 root 8u IPv4 378 TCP *:time (LISTEN)
inetd 353 root 10u IPv4 379 UDP *:time
inetd 353 root 11u IPv4 380 TCP *:auth (LISTEN)
inetd 353 root 12u IPv4 381 TCP *:linuxconf (LISTEN)
--------------------------------------------------------------------------