当前位置:Linux教程 - Linux - IP-Spoofing(IP欺骗)

IP-Spoofing(IP欺骗)

这是一篇简介IP-Spoofing(IP欺骗)原理的文章.想当年著名Hacker,Kevin与安全专家
下村勤之间的较量就是以IP-Spoofing开始的.这篇文章需要你具有一定的unix基础和tcpip概念,
IP-Spoofing 是一种比较复杂的攻击手段.但准确的说它是一次攻击的一个步骤.文章
中使用的一些标记:
A:目标主机
B:被信任主机
C:不可达主机
Z:发起攻击的主机
(1)2:主机1伪装成主机2

文章中常用的一种图解:
tick host a control host b
1 A --SYN---> B

tick:一段时间的泛指.
host a:一台加入到tcp会话中的机器.
control:tcp头中设置的相关的位.
host b:一台加入到tcp会话中的机器.

这里是说明主机A向主机B发了一条SYN置位的包.

在Unix主机中,信任的方式时非常简单的.假如你在主机A和主机B中各有一个账号.你希望在主
机A和主机B中能够比较方便的来回登录.你可以在自己的目录下建立一个.rhost文件.在A种的
文件中可以简单的写上" B username",在B中的类似(在/etc/hosts.equiv中可以为整个系统建
立信任关系,相关的具体语法可以参考其他资料).现在你就可以用那些以r开头的系统命令了,
而不需要每次都输入密码.看看发生了什么,所有的认证都是基于主机的,也就是基于ip的,只
要你是来自这个ip的就认为是可以信任的.ip-sproofing就是对基于ip认证的系统进行攻击的一
种手段.比如说rlogin命令,就是一个通过这种机制,可以不输入密码就登录到远程主机的命令.

我们都知道ip是无连接的,不可靠的协议.它的32bit的头中,包含了自己要去的
目的主机的ip地址,几乎所有的tcp/ip协议的传输都是被包含在ip包中发送的.它的
所有的可靠性都是由它的上层协议来保证的.如果不可达,icmp的不可达报文就会发送会主机.它
的无状态的特性,说明它不保存上一个包的任何状态.因此,我们就可以通过修改ip协议栈的方法,
把所需要的ip地址填写到我们所发送出去的ip包中,来达到冒充其他主机的目的.

tcp协议是保证传递可靠的上层协议,它通过多种方法实现可靠传递.但我们所关心的只
有两种,即数据的sequence号和Acknowledgement号.tcpip协议栈会对所有发出的数据分配seq号,
对所有接收到的数据,会发出ack以表示确认.因为它要处理丢包,重发等等情况.seq号可以是一个
32位的数字,所以它的范围在 0-- 4,294,967,295之间.所有的tcp头中的seq号是所发送的数据的
第一个字节的序号.ack号是下一个所希望得到的数据的seq号.
tcp还利用滑动窗口和窗口通告的方式来进行流控.窗口的大小是16比特的.所以这也限制
了在特定情况下的seq号的上限.这为我们以后猜测seq号,缩小了范围.其他的tcp中的置位信息,
如RST,PSH,FIN的意义可以参考一下相关的书籍.
在传送数据之前要建立连接,就是常说的3次握手,示意图如下

1 A ---SYN---> B

2 A <---SYN/ACK--- B

3 A ---ACK---> B


在(1)中,客户端会同时发送它的seq起始号(ISN).在(2)中,服务器会返回自己的ISN和对(1)中ISN
的一个回应ACK号(ISN(A)+1),在(3)中,客户端会返回对(2)中服务器的ISN的回应ACK号(ISN(B)+1).
因为现在并没有传递什么数据,所以现在的seq,ack都是为了以后传递数据所进行的初始化.

最重要的一点是,你要知道起始的seq号是如何被选择的和它们与时间变化所相关的联系.
一般来说当机器启动的时候,seq被初始化成1.这种管理,已经被公认为是不好的.在一般的
tcp_init()源程序的注释中你可以找到类似的注释.初始化的序列号(ISN)会每秒钟增加128,000,
大概一个32位的ISN在没有任何连接的情况下,9.32个小时后会发生循环,而且,每发生一次
connect()的调用,会增加64,000.
为什么要使用这种可预测的ISN选取方式呢?为什么不用随机的方法呢?因为我们知道每次
连接会有4个量来标记(一对tcp端口和ip地址).如果一个老的连接中的一个在网上游荡了很久的
包,现在被投递了过来.而由一个新的连接永了同样的端口对,我们只能用seq来区分数据的正确
性.如果每次用随机的seq,将无法保证seq号在这种情况下不会发生冲突.每次增大,将有效的解决
这个问题.但是也给安全留下了隐患.


攻击过程:
ip-spoofing攻击包括几个步骤:
1.找到要攻击的主机A
2.发现和它有关的信任主机B
3.将B利用某种方法攻击瘫痪
4.对A的seq号进行取样
5.猜测新的可能的seq号
6.用这个seq号进行尝试连接
7.如果连接成功,则执行一个命令,留下一个后门.

当然,一般由软件会配合整个攻击过程.一般攻击从一台你拥有root账号的主机开始,以获
取另一个主机的root账号为目的.

IP-spoofing的最大困难是你所进行的是一次盲攻击.因为你伪装成别的主机,所以中间的
路由器不会把包路由回来.当然主机B(被信任的主机)已经被你攻击瘫痪,它无法回应.而你要在无法
接受任何回应包的同时,参测可能的回应包,并替代主机B做回答.怎么样?不容易吧!这其中最需要的
猜测的就是seq号了.猜错了,目标主机就会丢弃你的包.


寻找主机A的信任主机,也是一件不太容易的事.你可以通过showmout命令或rpcinfo,
nslookup得到一些信息.这需要你有很丰富的经验.具体方法,请参考相关的书籍.实在不行,只能在
相邻的一些ip上进行猜测.


攻击信任主机使它瘫痪,也是必不可少的一步.但它本身也可以单独写一篇文章,所以
ip-spoofing是比较高级的攻击方法一种.这里你可以使用各种类型的flood(洪水)软件,进行攻击.
原理就是在一定时间内发出大量的包给目的主机,使主机资源耗尽,达到攻击的目的.

现在进入了主要部分.猜测目的主机的seq号.首先主机要以真实的身份做几次尝试性的连
接,把其中的ISN号记录下来.并对RTT(round-trip time)往返时间进行猜测.RTT将被用来猜测下一次
可能的ISN(配合128,000/秒,64,000每次连接的规律).一般要猜测很多次.在这之中可能会出现几种
情况:
1.如果猜测正确,数据将会放到接收缓冲区中.
2.如果seq小于目的主机所期望的seq号,包被丢弃
3.如果seq大于目的主机所期望的seq号,但是小于tcp的接受窗口范围,将被放到一个悬挂队列中,因
为有可能是后发送的数据,先到达了.
4.如果目的主机所期望的seq号,又不在tcp的接受窗口范围之内,包被丢弃.

下面是一个攻击的示意图:


1 Z(b) ---SYN---> A

2 B <---SYN/ACK--- A

3 Z(b) ---ACK---> A

4 Z(b) ---PSH---> A



攻击如果得手,一般会执行一个命令,比如``cat + + >> ~/.rhosts`` ,这使目标主机信任所
有的主机.由此也可以看到.rhost文件是多么的危险.
再强调一遍,这所有的一切都是建立在ip认证的基础上,所以ip认证的所有软件,都有同样的
问题.如果不是十分的必须,请不要使用 .rhost, /etc/host.equiv之类的文件,和r*命令.或者用你
的路由器把从外部来的对这种认证的请求全部屏蔽掉.

由于ISN的这种非随机的选取机制,使ip-spoofing能够得逞. Bellovin描述了一种解决方法.
每一次连接都有自己的seq空间,但是这些空间之间的数字没有明显的关联关系.例如:

ISN=M+F(localhost,localport,remotehost,remoteport)

M是一个计时器,F是一个加密散列值.F是无法计算的.用这种机制可以解决问题.

但是,毕竟Internet不可能在一夜之间改变.在Internet上到处潜伏着危机.

Ip-spoofing的软件,在很多地方可以找到.这里就不列举了.


sphinx Zhu
1999.4.19