。 + C7 q$ U% ?9 D2 R
IP欺骗的技术比较复杂,不是简单地照猫画老虎就能掌握,但作为常规攻击手段,有必要理解其原理,至少有利于自己的安全防范,易守难攻嘛。 0 g0 N$ ^# ?' g. A. ~; ~
% Y- e/ B4 K5 j0 z2 z
假设B上的客户运行rlogin与A上的rlogind通信: % U$ I; g% }- ^" v E" U2 o9 |3 J
/ ]0 k# ~+ P# ] K* F% U" b1. B发送带有SYN标志的数据段通知A需要建立TCP连接。并将TCP报头中的sequence number设置成自己本次连接的初始值ISN。 / Z1 _9 x G8 ?4 L
7 R3 A+ H3 l+ m9 P( v% V9 r/ U
2. A回传给B一个带有SYS+ACK标志的数据段,告之自己的ISN,并确认B发送来的第一个数据段,将acknowledge number设置成B的ISN+1。 8 o( Y$ i$ [; `0 B: b7 V, K, E$ v8 a
" b. H) d* Y8 h* v4 L- y2 |. n
3. B确认收到的A的数据段,将acknowledge number设置成A的ISN+1。
+ J0 ]% i7 n, \* U9 a
; |! O7 t* T% W+ W+ k4 pB ---- SYN ----> A
1 _7 K8 d# n. [ t2 fB <---- SYN+ACK A
5 {# |" D: ~: i' a$ _B ---- ACK ----> A * W: c9 A2 C% ]) D- E7 F
$ b* v! F) d T- l# t; w# a
TCP使用的sequence number是一个32位的计数器,从0-4294967295。TCP为每一个连接选择一个初始序号ISN,为了防止因为延迟、重传等扰乱三次握手,ISN不能随便选取,不同系统有不同算法。理解TCP如何分配ISN以及ISN随时间变化的规律,对于成功地进行IP欺骗攻击很重要。 ; N2 ?/ k: V5 V& B7 W
& B1 c5 v- W( T1 N) B* `1 K
基于远程过程调用RPC的命令,比如rlogin、rcp、rsh等等,根据/etc/hosts.equiv以及$HOME/.rhosts文件进行安全校验,其实质是仅仅根据信源IP地址进行用户身份确认,以便允许或拒绝用户RPC。关于上述两个文件请man,不喜欢看英文就去Unix版看看我以前灌过的一瓢水。
0 [; |) z/ n* Y9 c
# K4 S. L- b3 j3 W% nIP欺骗攻击的描述: 9 T0 C" S7 n2 K8 `* @+ O$ C
5 ]/ N6 @( F: B: K& e* K7 M$ k: K1. 假设Z企图攻击A,而A信任B,所谓信任指/etc/hosts.equiv和$HOME/.rhosts中有相关设置。注意,如何才能知道A信任B呢?没有什么确切的办法。我的建议就是平时注意搜集蛛丝
' i9 x* ^5 z! z+ O0 E马迹,厚积薄发。一次成功的攻击其实主要不是因为技术上的高明,而是因为信息搜集的广泛翔实。动用了自以为很有成就感的技术,却不比人家酒桌上的巧妙提问,攻击只以成功为终极目标,不在乎手段。 0 X* `- w$ t) s# i4 Z, z
) d- W+ {% r3 b6 P2. 假设Z已经知道了被信任的B,应该想办法使B的网络功能暂时瘫痪,以免对攻击造成干扰。著名的SYN flood常常是一次IP欺骗攻击的前奏。请看一个并发服务器的框架: $ T. i+ j# h4 ]7 V
2 C& K, x8 Q% @) q) S6 d5 J
int initsockid, newsockid;
& d& O/ y- R' t/ f0 T+ A! U6 K& @if ((initsockid = socket(...)) <0) {
8 ^8 `$ b( U7 A* R( d' Serror("can't create socket");
4 s) q3 E; N6 X$ y' w} ' G2 a# V7 b2 j8 E) K. m& z
if (bind(initsockid, ...) <0) {
! W& k# H2 l t2 g7 J* Uerror("bind error");
! k+ I% I, G' ?* g1 H9 q/ C0 o}
8 n0 i- G3 H" A- m ^3 C0 Lif (listen(initsockid, 5) <0) {
! L1 L: F$ B d3 e8 N) U) ]" f1 [) yerror("listen error"); 2 K. K; k6 c+ L, ^# _4 J
}
$ F, T+ ]1 w* P9 x0 x; Nfor (;;) {
' U3 G* G- }& ]' S% p' [& inewsockid = accept(initsockid, ...); /* 阻塞 */ , S8 `2 ^4 e6 y4 V% r% {# N4 ?
if (newsockid <0) { + J# O: ^, a& K8 }
error("accept error");
" a. z* Y$ ~0 [2 w7 Y* x7 S}
- W9 k1 d# C% M. a/ sif (fork() == 0) { /* 子进程 */
% i; B1 a6 }' q4 u4 L! g6 U( C; Zclose(initsockid); 0 r- x2 I3 p- |3 V$ A. j5 p0 f
do(newsockid); /* 处理客户方请求 */ + l2 M' `7 Z1 L9 U, Z
exit(0);
k: s% g5 C4 ~+ K# J}
* x( S) v. ^3 u5 ^) gclose(newsockid);
5 u+ ^- [5 B. t6 b5 d& F4 V# W( d} , b) ~6 R' E( ~' B: h
4 ^, U- F7 F; b2 X& |listen函数中第二个参数是5,意思是在initsockid上允许的最大连接请求数目。如果某个时刻initsockid上的连接请求数目已经达到5,后续到达initsockid的连接请求将被TCP丢弃。注意一旦连接通过三次握手建立完成,accept调用已经处理这个连接,则TCP连接请求队列空出一个位置。所以这个5不是指initsockid上只能接受5个连接请求。SYN flood正是一种Denial of Service,导致B的网络功能暂 碧被尽?nbsp;, O( L/ }' L0 M: d+ L
: |1 K/ [2 G* e, f3 j+ Q
Z向B发送多个带有SYN标志的数据段请求连接,注意将信源IP地址换成一个不存在的主机X;B向子虚乌有的X发送SYN+ACK数据段,但没有任何来自X的ACK出现。B的IP层会报告B的TCP层,X不可达,但B的TCP层对此不予理睬,认为只是暂时的。于是B在这个initsockid上再也不能接收正常的连接请求。
: a6 u/ ?- {4 I5 Y& k& g% I5 E! M! R1 g3 j. l
Z(X) ---- SYN ----> B ; L( ~. q7 V1 Z# L$ R) v+ f
Z(X) ---- SYN ----> B
. V" \' \+ Y% P" E7 [) [1 ZZ(X) ---- SYN ----> B
* w; r: m0 k9 K y( `Z(X) ---- SYN ----> B + K9 Q& Y; T6 [9 o
Z(X) ---- SYN ----> B / W9 ?9 ^! ]( y8 A* [' l2 e, u
...... ' y2 r+ x5 t: T7 j9 i$ M
X <---- SYN+ACK B - P+ o# q$ G' j0 V; h& o5 X" }( }
X <---- SYN+ACK B " U8 t8 [* V- G1 {+ S4 I
X <---- SYN+ACK B . S2 f) x" h p" I# d
X <---- SYN+ACK B
& Z- y* U& _) u$ ]7 B# xX <---- SYN+ACK B " f( E5 a& Y% X) ?' X7 ]
......
7 G D( k; F7 k4 \! c
$ T3 \' [9 c' W! K. t7 P; c作者认为这样就使得B网络功能暂时瘫痪,可我觉得好象不对头。因为B虽然在initsockid上无法接收TCP连接请求,但可以在another initsockid上接收,这种SYN flood应该只对特定的
- Y6 F1 E( O8 O8 d服务(端口),不应该影响到全局。当然如果不断地发送连接请求,就和用ping发洪水包一个道理,使得B的TCP/IP忙于处理负载增大。至于SYN flood,回头有机会我单独灌一瓢有关DoS的。如何使B的网络功能暂 碧被居 很多办法,根据具体情况而定,不再赘述。 & I2 J; d$ n+ z% u0 r! d
3 t/ e7 C' }. y1 P4 ^% S3. Z必须确定A当前的ISN。首先连向25端口(SMTP是没有安全校验机制的),与1中类似,不过这次需要记录A的ISN,以及Z到A的大致的RTT(round trip time)。这个步骤要重复多次以便求出 . h. r7 g1 D3 D; g
RTT的平均值。现在Z知道了A的ISN基值和增加规律(比如每秒增加128000,每次连接增加64000),也知道了从Z到A需要RTT/2的时间。必须立即进入攻击,否则在这之间有其他主机与A连接,
. h" [6 c5 l2 x, H# z- W( VISN将比预料的多出64000。 4 p% I/ O1 v: {2 _
) W5 d! s, h* t4. Z向A发送带有SYN标志的数据段请求连接,只是信源IP改成了B,注意是针对TCP513端口(rlogin)。A向B回送SYN+ACK数据段,B已经无法响应(凭什么?按照作者在2中所说,估计还达不到这个效果,因为Z必然要模仿B发起connect调用,connect调用会完成全相关,自动指定本地socket地址和端口,可事实上B很可能并没有这样一个端口等待接收数据。除非Z模仿B发起 ( i7 l1 Z& S- A9 F- [
连接请求时打破常规,主动在客户端调用bind函数,明确完成全相关,这样必然知道A会向B的某个端口回送,在2中也针对这个端口攻击B。可是如果这样,完全不用攻击B,bind的时候
5 ^+ g+ o0 p1 e! O指定一个B上根本不存在的端口即可。我也是想了又想,还没来得及看看老外的源代码,不妥之处有待商榷。总之,觉得作者好象在蒙我们,他自己也没有实践成功过吧。),B的TCP层只是
0 s" c0 Q- a" \* g简单地丢弃A的回送数据段。
# a, d1 k* Q. D9 J$ j, z4 c+ X& x; U. \3 s0 f' r$ G+ {
5. Z暂停一小会儿,让A有足够时间发送SYN+ACK,因为Z看不到这个包。然后Z再次伪装成B向A发送ACK,此时发送的数据段带有Z预测的A的ISN+1。如果预测准确,连接建立,数据传送开始。问题在于即使连接建立,A仍然会向B发送数据,而不是Z,Z仍然无法看到A发往B的数据段,Z必须蒙着头按照rlogin协议标准假冒B向A发送类似 "cat + + >> ~/.rhosts" 这样的命令,于是攻击完成。如果预测不准确,A将发送一个带有RST标志的数据段异常终止连接,Z只有从头再来。
" e5 g, O: N1 R/ r9 b3 A- c% D7 O& D2 X# _. E6 y; l
Z(B) ---- SYN ----> A
- q$ f V# ~+ n0 [9 R4 rB <---- SYN+ACK A 5 E( \/ C% t& g& C. \5 i
Z(B) ---- ACK ----> A
; W! V; \( }$ i, q0 ]Z(B) ---- PSH ----> A ; E' f2 T6 v+ y( F4 H, E5 @
......
7 O/ G- @: q- X7 y2 G( ^7 j' n& o" J( Z$ m$ |
6. IP欺骗攻击利用了RPC服务器仅仅依赖于信源IP地址进行安全校验的特性,建议阅读rlogind的源代码。攻击最困难的地方在于预测A的ISN。作者认为攻击难度虽然大,但成功的可能性
! E& B, }+ s6 [0 h8 ?也很大,不是很理解,似乎有点矛盾。考虑这种情况,入侵者控制了一台由A到B之间的路由器,假设Z就是这台路由器,那么A回送到B的数据段,现在Z是可以看到的,显然攻击难度
5 o* Q) X: X: R4 Q" W$ l骤然下降了许多。否则Z必须精确地预见可能从A发往B的信息,以及A期待来自B的什么应答信息,这要求攻击者对协议本身相当熟悉。同时需要明白,这种攻击根本不可能在交互状态下完 2 i/ ]+ n2 ?' Z8 Q: S) {' M
成,必须写程序完成。当然在准备阶段可以用netxray之类的工具进行协议分析。
9 m9 u% ^ e5 l M
8 z; N5 e0 M/ [# b4 X7 [7. 如果Z不是路由器,能否考虑组合使用ICMP重定向以及ARP欺骗等技术?没有仔细分析过,只是随便猜测而已。并且与A、B、Z之间具体的网络拓扑有密切关系,在某些情况下显然大幅度
- }( o8 i& [/ M5 e5 q$ i降低了攻击难度。注意IP欺骗攻击理论上是从广域网上发起的,不局限于局域网,这也正是这种攻击的魅力所在。利用IP欺骗攻击得到一个A上的shell,对于许多高级入侵者,得到目标主
9 t+ B/ j6 D; n' P% G4 ~机的shell,离root权限就不远了,最容易想到的当然是接下来进行buffer overflow攻击。
7 t. V3 J9 r$ Y/ O% w1 E/ H% Z* T. b1 L2 G, x! Y: d7 w
8. 也许有人要问,为什么Z不能直接把自己的IP设置成B的?这个问题很不好回答,要具体分析网络拓扑,当然也存在ARP冲突、出不了网关等问题。那么在IP欺骗攻击过程中是否存在ARP冲突问题。回想我前面贴过的ARP欺骗攻击,如果B的ARP Cache没有受到影响,就不会出现ARP冲突。如果Z向A发送数据段时,企图解析A的MAC地址或者路由器的MAC地址,必然会发送ARP请求包,但这个ARP请求包中源IP以及源MAC都是Z的,自然不会引起ARP冲突。而ARP Cache只会被ARP包改变,不受IP包的影响,所以可以肯定地说,IP欺骗攻击过程中不存在ARP冲突。相反,如果Z修改了自己的IP,这种ARP冲突就有可能出现,示具体情况而言。攻击中连带B一起攻击了,其目的无非是防止B干扰了攻击过程,如果B本身已经down掉,那是再好不过(是吗?)。 0 l- B* U/ P/ u- L T
$ z; V* d2 T+ y9 m
9. fakeip曾经沸沸扬扬了一下,我对之进行端口扫描,发现其tcp端口113是接收入连接的。和IP欺骗等没有直接联系,和安全校验是有关系的。当然,这个东西并不如其名所暗示,对IP层没有任何动作。 + e5 N: S7 u, |# }
" g- r$ x2 X6 t2 E. k: h
10. 关于预测ISN,我想到另一个问题。就是如何以第三方身份切断A与B之间的TCP连接,实际上也是预测sequence number的问题。尝试过,也很困难。如果Z是A与B之间的路由器,就不用说了;或者Z动用了别的技术可以监听到A与B之间的通信,也容易些;否则预测太难。作者在3中提到连接A的25端口,可我想不明白的是513端口的ISN和25端口有什么关系?看来需要看看TCP/IP内部实现的源代码。
/ L V& m, ^+ R2 ]( L
7 z- X2 Y, e/ j- @( L未雨绸缪
$ g& J, M5 x0 O. Z7 h8 _
' V7 ^; E' h: ^% E; T虽然IP欺骗攻击有着相当难度,但我们应该清醒地意识到,这种攻击非常广泛,入侵往往由这里开始。预防这种攻击还是比较容易的,比如删除所有的/etc/hosts.equiv、$HOME/.rhosts文件,修改/etc/inetd.conf文件,使得RPC机制无法运做,还可以杀掉portmapper等等。设置路由器,过滤来自外部而信源地址却是内部IP的报文。cisio公司的产品就有这种功能。不过路由器只防得了外部入侵,内部入侵呢?
9 g# O6 g# G9 z1 \3 W( Q+ _. U0 m8 h+ }- x4 q' G& q1 a
TCP的ISN选择不是随机的,增加也不是随机的,这使攻击者有规可循,可以修改与ISN相关的代码,选择好的算法,使得攻击者难以找到规律。估计Linux下容易做到,那solaris、irix、hp-unix还有aix呢?sigh , t% O9 r4 ?3 X
) |, S6 Q& H' N& y- G+ N虽然作者纸上谈兵,但总算让我们了解了一下IP欺骗攻击,我实验过预测sequence number,不是ISN,企图切断一个TCP连接,感觉难度很大。作者建议要找到规律,不要盲目预测,这需要时间和耐心。现在越发明白什么是那种锲而不舍永远追求的精神,我们所向往的传奇故事背后有着如此沉默的艰辛和毅力,但愿我们学会的是这个,而不是浮华与喧嚣。一个现成的bug足以让你取得root权限,可你在做什么,你是否明白?我们太肤浅了......
0 T/ G0 J# S2 d% N0 S 浅了...... |