|
用户名:headwolf 笔名:headwolf 地区: |
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
IP欺骗原理精解和防范手段综述
IP欺骗原理精解和防范手段综述
即使是很好的实现了TCP/IP协议,由于它本身有着一些不安全的地方,从而可以对TCP/IP网络进行攻击。这些攻击包括序列号欺骗,路由攻击,源地址欺骗和授权欺骗。本文除了介绍IP欺骗攻击方法外,还介绍怎样防止这个攻击手段。
上述攻击是建立在攻击者的计算机(包括路由)是连在INTERNET上的。这里的攻击方法是针对TCP/IP本身的缺陷的,而不是某一具体的实现。
实际上,IP 欺骗不是进攻的结果,而是进攻的手段。进攻实际上是信任关系的破坏。
IP欺骗原理
信任关系
在Unix领域中,信任关系能够很容易得到。假如在主机A和B上各有一个帐户,在使用当中会发现,在主机A上使用时需要输入在A上的相应帐户,在主机B上使用时必须输入在B上的帐户,主机A和B把你当作两个互不相关的用户,显然有些不便。为了减少这种不便,可以在主机A和主机B中建立起两个帐户的相互信任关系。在主机A和主机B上你的home目录中创建.rhosts 文件。从主机A上,在你的home目录中输入'echo " B username " > ~/.rhosts' ;从主机B上,在你的home目录中输入'echo " A username " >~/.rhosts' 。至此,你能毫无阻碍地使用任何以r*开头的远程登录如:rlogin,rcall,rsh等,而无口令验证的烦恼。这些命令将允许以地址为基础的验证,或者允许或者拒绝以IP地址为基础的存取服务。
这里的信任关系是基于IP地址的。
Rlogin
Rlogin 是一个简单的客户/服务器程序,它利用TCP传输。Rlogin 允许用户从一台主机登录到另一台主机上,并且,如果目标主机信任它,Rlogin 将允许在不应答口令的情况下使用目标主机上的资源。安全验证完全是基于源主机的IP 地址。因此,根据以上所举的例子,我们能利用Rlogin 来从B远程登录到A,而且不会被提示输入口令。
TCP 序列号预测
IP只是发送数据包,并且保证它的完整性。如果不能收到完整的IP数据包,IP会向源地址发送一个ICMP 错误信息,希望重新处理。然而这个包也可能丢失。由于IP是非面向连接的,所以不保持任何连接状态的信息。每个IP数据包被松散地发送出去,而不关心前一个和后一个数据包的情况。由此看出,可以对IP堆栈进行修改,在源地址和目的地址中放入任意满足要求的IP地址,也就是说,提供虚假的IP地址。
TCP提供可靠传输。可靠性是由数据包中的多位控制字来提供的,其中最重要的是数据序列和数据确认,分别用SYN和ACK来表示。TCP 向每一个数据字节分配一个序列号,并且可以向已成功接收的、源地址所发送的数据包表示确认(目的地址ACK 所确认的数据包序列是源地址的数据包序列,而不是自己发送的数据包序列)。ACK在确认的同时,还携带了下一个期望获得的数据序列号。显然,TCP提供的这种可靠性相对于IP来说更难于愚弄。
序列编号、确认和其它标志信息
由于TCP是基于可靠性的,它能够提供处理数据包丢失,重复或是顺序紊乱等不良情况的机制。实际上,通过向所传送出的所有字节分配序列编号,并且期待接收端对发送端所发出的数据提供收讫确认,TCP 就能保证可靠的传送。接收端利用序列号确保数据的先后顺序,除去重复的数据包。TCP 序列编号可以看作是32位的计数器。它们从0至2^32-1 排列。每一个TCP连接(由一定的标示位来表示)交换的数据都是顺序编号的。在TCP数据包中定义序列号(SYN)的标示位位于数据段的前端。确认位(ACK)对所接收的数据进行确认,并且指出下一个期待接收的数据序列号。
TCP通过滑动窗口的概念来进行流量控制。设想在发送端发送数据的速度很快而接收端接收速度却很慢的情况下,为了保证数据不丢失,显然需要进行流量控制,协调好通信双方的工作节奏。所谓滑动窗口,可以理解成接收端所能提供的缓冲区大小。TCP利用一个滑动的窗口来告诉发送端对它所发送的数据能提供多大的缓冲区。由于窗口由16位bit所定义,所以接收端TCP 能最大提供65535个字节的缓冲。由此,可以利用窗口大小和第一个数据的序列号计算出最大可接收的数据序列号。
其它TCP标示位有RST(连接复位,Reset the connection)、PSH(压入功能,Push function)和FIN (发送者无数据,No more data from sender)。如果RST 被接收,TCP连接将立即断开。RST 通常在接收端接收到一个与当前连接不相关的数据包时被发送。有些时候,TCP模块需要立即传送数据而不能等整段都充满时再传。一个高层的进程将会触发在TCP头部的PSH标示,并且告诉TCP模块立即将所有排列好的数据发给数据接收端。FIN 表示一个应用连接结束。当接收端接收到FIN时,确认它,认为将接收不到任何数据了。
TCP序列号预测最早是由Morris对这一安全漏洞进行阐述的。他使用TCP序列号预测,即使是没有从服务器得到任何响应, 来产生一个TCP包序列。这使得他能欺骗在本地网络上的主机。
通常TCP连接建立一个包括3次握手的序列。客户选择和传输一个初始的序列号(SEQ标志)ISN C,并设置标志位SYN=1,告诉服务器它需要建立连接。服务器确认这个传输,并发送它本身的序列号ISN S,并设置标志位ACK,同时告知下一个期待获得的数据序列号是ISN=1。客户再确认它。在这三次确认后,开始传输数据。整个过程如下所示:(C:Client S:Server)
C---S: SYN(ISN C )
S---C: SYN(ISN S ) ,ACK(ISN C )
C---S: ACK(ISN S )
C---S:数据 或S---C:数据
也就是说对一个会话,C必须得到ISN S确认。ISN S可能是一个随机数。
了解序数编号如何选择初始序列号和如何根据时间变化是很重要的。似乎应该有这种情况,当主机启动后序列编号初始化为1,但实际上并非如此。初始序列号是由tcp_init函数确定的。ISN每秒增加128000,如果有连接出现,每次连接将把计数器的数值增加64000。很显然,这使得用于表示ISN的32位计数器在没有连接的情况下每9.32 小时复位一次。之所以这样,是因为这样有利于最大限度地减少旧有连接的信息干扰当前连接的机会。这里运用了2MSL 等待时间的概念(不在本文讨论的范围之内)。如果初始序列号是随意选择的,那么不能保证现有序列号是不同于先前的。假设有这样一种情况,在一个路由回路中的数据包最终跳出了循环,回到了"旧有"的连接(此时其实是不同于前者的现有连接),显然会发生对现有连接的干扰。
假设一个入侵者X有一种方法,能预测ISN S。在这种情况下,他可能将下列序号送给主机T来模拟客户的真正的ISN S:
X---S: SYN(ISN X ) ,SRC = T
S---T: SYN(ISN S ) ,ACK(ISN X )
X---S: ACK(ISN S ) ,SRC =T
尽管消息S*T并不到X,但是X能知道它的内容,因此能发送数据。如果X要对一个连接实施攻击,这个连接允许执行命令,那么另外的命令也能执行。
那么怎样产生随机的ISN?在Berkeley系统,最初的序列号变量由一个常数每秒加一产生,等到这个常数一半时,就开始一次连接。这样,如果开始了一个合法连接,并观察到一个ISN S在用,便可以计算,有很高可信度,ISN S 用在下一个连接企图。
Morris 指出,回复消息
S---T:SYN(ISN S ) ,ACK(ISN X )
事实上并不消失,真正主机将收到它,并试图重新连接。这并不是一个严重的障碍。
Morris发现,通过模仿一个在T上的端口,并向那个端口请求一个连接,他就能产生序列溢出,从而让它看上去S*T消息丢失了。另外一个方法,可以等待知道T关机或重新启动。
下面详细的介绍一下。
IP欺骗
IP欺骗由若干步骤组成,这里先简要地描述一下,随后再做详尽地解释。先做以下假定:首先,目标主机已经选定。其次,信任模式已被发现,并找到了一个被目标主机信任的主机。黑客为了进行IP欺骗,进行以下工作:使得被信任的主机丧失工作能力,同时采样目标主机发出的TCP 序列号,猜测出它的数据序列号。然后,伪装成被信任的主机,同时建立起与目标主机基于地址验证的应用连接。如果成功,黑客可以使用一种简单的命令放置一个系统后门,以进行非授权操作。
使被信任主机丧失工作能力
一旦发现被信任的主机,为了伪装成它,往往使其丧失工作能力。由于攻击者将要代替真正的被信任主机,他必须确保真正被信任的主机不能接收到任何有效的网络数据,否则将会被揭穿。有许多方法可以做到这些。这里介绍"TCP SYN 淹没"。
前面已经谈到,建立TCP连接的第一步就是客户端向服务器发送SYN请求。 通常,服务器将向客户端发送SYN/ACK 信号。这里客户端是由IP地址确定的。客户端随后向服务器发送ACK,然后数据传输就可以进行了。然而,TCP处理模块有一个处理并行SYN请求的最上限,它可以看作是存放多条连接的队列长度。其中,连接数目包括了那些三步握手法没有最终完成的连接,也包括了那些已成功完成握手,但还没有被应用程序所调用的连接。如果达到队列的最上限,TCP将拒绝所有连接请求,直至处理了部分连接链路。因此,这里是有机可乘的。
黑客往往向被进攻目标的TCP端口发送大量SYN请求,这些请求的源地址是使用一个合法的但是虚假的IP地址(可能使用该合法IP地址的主机没有开机)。而受攻击的主机往往是会向该IP地址发送响应的,但可惜是杳无音信。与此同时IP包会通知受攻击主机的TCP:该主机不可到达,但不幸的是TCP会认为是一种暂时错误,并继续尝试连接(比如继续对该IP地址进行路由,发出SYN/ACK数据包等等),直至确信无法连接。
当然,这时已流逝了大量的宝贵时间。值得注意的是,黑客们是不会使用那些正在工作的IP地址的,因为这样一来,真正IP持有者会收到SYN/ACK响应,而随之发送RST给受攻击主机,从而断开连接。前面所描述的过程可以表示为如下模式。
1 Z (X) ---SYN ---> B
Z (X) ---SYN ---> B
Z (X) ---SYN ---> B
2 X <---SYN/ACK-- B
X <---SYN/ACK-- B
3 X <--- RST --- B
在时刻1时,攻击主机把大批SYN 请求发送到受攻击目标(在此阶段,是那个被信任的主机),使其TCP队列充满。在时刻2时,受攻击目标向它所相信的IP地址(虚假的IP)作出SYN/ACK反应。在这一期间,受攻击主机的TCP模块会对所有新的请求予以忽视。不同的TCP 保持连接队列的长度是有所不同的。BSD 一般是5,Linux一般是6。使被信任主机失去处理新连接的能力,所赢得的宝贵空隙时间就是黑客进行攻击目标主机的时间,这使其伪装成被信任主机成为可能。
序列号取样和猜测
前面已经提到,要对目标主机进行攻击,必须知道目标主机使用的数据包序列号。现在,我们来讨论黑客是如何进行预测的。他们先与被攻击主机的一个端口(SMTP是一个很好的选择)建立起正常的连接。通常,这个过程被重复若干次,并将目标主机最后所发送的ISN存储起来。黑客还需要估计他的主机与被信任主机之间的RTT时间(往返时间),这个RTT时间是通过多次统计平均求出的。RTT 对于估计下一个ISN是非常重要的。前面已经提到每秒钟ISN增加128000,每次连接增加64000。现在就不难估计出ISN的大小了,它是128000乘以RTT的一半,如果此时目标主机刚刚建立过一个连接,那么再加上一个64000。再估计出ISN大小后,立即就开始进行攻击。当黑客的虚假TCP数据包进入目标主机时,根据估计的准确度不同,会发生不同的情况:
·如果估计的序列号是准确的,进入的数据将被放置在接收缓冲器以供使用。
·如果估计的序列号小于期待的数字,那么将被放弃。
·如果估计的序列号大于期待的数字,并且在滑动窗口(前面讲的缓冲)之内,那么,该数据被认为是一个未来的数据,TCP模块将等待其它缺少的数据。如果估计的序列号大于期待的数字,并且不在滑动窗口(前面讲的缓冲)之内,那么,TCP将会放弃该数据并返回一个期望获得的数据序列号。下面将要提到,黑客的主机并不能收到返回的数据序列号。
1 Z(B) ----SYN ---> A
2 B <---SYN/ACK--- A
3 Z(B) -----ACK---> A
4 Z(B) ---——PSH---> A
攻击者伪装成被信任主机的IP 地址,此时,该主机仍然处在停顿状态(前面讲的丧失处理能力),然后向目标主机的513端口(rlogin的端口号)发送连接请求,如时刻1所示。在时刻2,目标主机对连接请求作出反应,发送SYN/ACK数据包给被信任主机(如果被信任主机处于正常工作状态,那么会认为是错误并立即向目标主机返回RST数据包,但此时它处于停顿状态)。按照计划,被信任主机会抛弃该SYN/ACK数据包。然后在时刻3,攻击者向目标主机发送ACK数据包,该ACK使用前面估计的序列号加1(因为是在确认)。如果攻击者估计正确的话,目标主机将会接收该ACK 。至耍,将开始数据传输。一般地,攻击者将在系统中放置一个后门,以便侵入。经常会使用 ′cat ++ >> ~/.rhosts′。之所以这样是因为,这个办法迅速、简单地为下一次侵入铺平了道路。
一个和这种TCP序列号攻击相似的方法,是使用NETSTAT服务。在这个攻击中,入侵者模拟一个主机关机了。如果目标主机上有NETSTAT,它能提供在另一端口上的必须的序列号。这取消了所有要猜测的需要。
IP欺骗的防止
防止的要点在于,这种攻击的关键是相对粗糙的初始序列号变量在Berkeley系统中的改变速度。TCP协议需要这个变量每秒要增加25000次。Berkeley 使用的是相对比较慢的速度。但是,最重要的是,是改变间隔,而不是速度。
我们考虑一下一个计数器工作在250000Hz时是否有帮助。我们先忽略其他发生的连接,仅仅考虑这个计数器以固定的频率改变。
为了知道当前的序列号,发送一个SYN包,收到一个回复:
X---S: SYN(ISN X )
S---X: SYN(ISN S ) ,ACK(ISN X ) (1)
第一个欺骗包,它触发下一个序列号,能立即跟随服务器对这个包的反应:
X---S: SYN(ISN X ) ,SRC = T (2)
序列号ISN S用于回应了:
S---T: SYN(ISN S ) ,ACK(ISN X )
是由第一个消息和服务器接收的消息唯一决定。这个号码是X和S的往返精确的时间。这样,如果欺骗能精确地测量和产生这个时间,即使是一个4-U时钟都不能击退这次攻击。
抛弃基于地址的信任策略
阻止这类攻击的一种非常容易的办法就是放弃以地址为基础的验证。不允许r*类远程调用命令的使用;删除.rhosts 文件;清空/etc/hosts.equiv 文件。这将迫使所有用户使用其它远程通信手段,如telnet、ssh、skey等等。
进行包过滤
如果您的网络是通过路由器接入Internet 的,那么可以利用您的路由器来进行包过滤。确信只有您的内部LAN可以使用信任关系,而内部LAN上的主机对于LAN以外的主机要慎重处理。您的路由器可以帮助您过滤掉所有来自于外部而希望与内部建立连接的请求。
使用加密方法
阻止IP欺骗的另一种明显的方法是在通信时要求加密传输和验证。当有多种手段并存时,可能加密方法最为适用。
使用随机化的初始序列号
黑客攻击得以成功实现的一个很重要的因素就是,序列号不是随机选择的或者随机增加的。Bellovin 描述了一种弥补TCP不足的方法,就是分割序列号空间。每一个连接将有自己独立的序列号空间。序列号将仍然按照以前的方式增加,但是在这些序列号空间中没有明显的关系。可以通过下列公式来说明:
ISN =M+F(localhost,localport ,remotehost ,remoteport )
M:4微秒定时器
F:加密HASH函数。
F产生的序列号,对于外部来说是不应该能够被计算出或者被猜测出的。Bellovin 建议F是一个结合连接标识符和特殊矢量(随机数,基于启动时间的密码)的HASH函数 。
IP欺骗攻击法
IP欺骗与盗用原理
IP欺骗攻击
数据包
包"(Packet)是TCP/IP协议通信传输中的数据单位,一般也称"数据包"。有人说,局域网中传输的不是"帧"(Frame)吗?没错,但是TCP/IP协议是工作在OSI模型第三层(网络层)、第四层(传输层)上的,而帧是工作在第二层(数据链路层)。上一层的内容由下一层的内容来传输,所以在局域网中,"包"是包含在"帧"里的。
OSI(Open System Interconnection,开放系统互联)模型是由国际标准化组织(ISO)定义的标准,它定义了一种分层体系结构,在其中的每一层定义了针对不同通信级别的协议。OSI模型有7层,1-7层分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。OSI模型在逻辑上可分为两个部分:低层的1-4层关注的是原始数据的传输;高层的5-7层关注的是网络下的应用程序。
我们可以用一个形象一些的例子对数据包的概念加以说明:我们在邮局邮寄产品时,虽然产品本身带有自己的包装盒,但是在邮寄的时候只用产品原包装盒来包装显然是不行的。必须把内装产品的包装盒放到一个邮局指定的专用纸箱里,这样才能够邮寄。这里,产品包装盒相当于数据包,里面放着的产品相当于可用的数据,而专用纸箱就相当于帧,且一个帧中只有一个数据包。
"包"听起来非常抽象,那么是不是不可见的呢?通过一定技术手段,是可以感知到数据包的存在的。比如在Windows 2000 Server中,把鼠标移动到任务栏右下角的网卡图标上(网卡需要接好双绞线、连入网络),就可以看到"发送:××包,收到:××包"的提示,如图1所示。通过数据包捕获软件,也可以将数据包捕获并加以分析。
数据包的结构非常复杂,不是三言两语能够说清的,在这里我们主要了解一下它的关键构成就可以了,这对于理解TCP/IP协议的通信原理是非常重要的。数据包主要由"目的IP地址"、"源IP地址"、"净载数据"等部分构成
数据包的结构与我们平常写信非常类似,目的IP地址是说明这个数据包是要发给谁的,相当于收信人地址;源IP地址是说明这个数据包是发自哪里的,相当于发信人地址;而净载数据相当于信件的内容。
正是因为数据包具有这样的结构,安装了TCP/IP协议的计算机之间才能相互通信。我们在使用基于TCP/IP协议的网络时,网络中其实传递的就是数据包。理解数据包,对于网络管理的网络安全具有至关重要的意义。
网络数据包截获机制
网络数据截获方法
网络数据包截获机制是网络入侵检测系统的基础组件。一般指通过截获整个网络的所有信息流量,根据信息源主机,目标主机,服务协议端口等信息简单过滤掉不关心的数据,再将用户感兴趣的数据发送给更高层的应用程序进行分析。流程图如下:
图5.1 网络数据截获流程
一方面要,网络截取模块要能保证截取到所有网络上的数据包,尤其是检测到被分片的数据包(这可能蕴涵着攻击)。
另方面,数据截取模块截取数据包的效率也是很重要的。
它直接影响整个入侵检测系统的运行速度。
5.2各种数据流截获方法
5.2.1 利用广播截取网络数据流
数据包的截取技术是依赖网卡的。而网卡可以通过广播监听到以太网络上的数据包,这就是数据包截取技术的基础。
要想截获不是给自己数据流,就必须绕开系统正常工作的机制,直接通过网卡的混杂模式,使之可以接受目标地址不是自己的MAC地址的数据包,直接访问数据链路层,取数据。
5.2.2各系统截取数据包机制
Linux系统为用户提供一种在理论上是数据链路层的,基于网卡驱动程序的,可以不用操作系统自身协议栈的接口(也称套接字)-SockPacket. 这种套接字可以从数据链路层(就是网线)上直接截取所有链路层数据包。而Unix则是通过Libpcap库直接与内核交互,实现网络截取。如:Libpcap,Tcpdump等。
BSD Packet Filter(BPF)机制来截取数据包。BPF可以说是各系统中最棒的截获方式。很多开源嗅探工具就是基于它而开发的。Windows系统也有类似情况,如:win系列上有*.vxd (VxD,VirtualDeviceDrive)(packet*.vxd) 和 网卡.sys(为网卡芯片所开发)来驱动网卡截取数据包。
5.2.3 BPF过滤
Unix&Linux系统有两种数据链路层截取机制,分别是BSD系列系统(NetBSD,OpenBSD,FreeBSD等)的BPF和Linux的SOCKET_PACKET。
BPF过滤
BPF主要由两大部分组成:
网络头接口
数据包过滤器。
网络头接口从网络设备驱动程序处收集数据包复制(在提交给系统协议栈之前),并传递给正在截获数据包的应用程序。而过滤器决定某一数据包是被接受或者拒绝以及如果被接受,数据包的那些部分会被复制给应用程序。
如:TCPDump注:(1), Libpcap, Sniffer, eeye,等。一般情况,网卡驱动通过网卡把网络上的电平信号转化成数据包,再把截取到的数据传给系统自带的协议栈,然后在交由系统处理。这种方式与Unix下的BPF不同,它使得网卡驱动在把从网络截取的数据提交给系统之前,先拷贝一份给BPF,再由BPF 决定是否符合规则,不符合则丢弃,符合则存放到内存指定区,等待处理。
当然,BPF对网卡驱动交给系统协议栈的数据包不做任何干涉。
注1:TCPDump是伯克利实验室的Van Jacobson,Craig Leres和Stenven McCanne为分析TCP性能问题而写的跨平台的监听程序。
5.3基于Libpcap库的通用数据截获技术
Libpcap是用户态的数据包截获API函数接口,有独立和可移植行。最初,Libpcap是为了强大的,健壮TCPDump而编写的。它支持BPF过滤机制。Snort就是依赖于libpcap库进行数据包截取的程序之一(还有Ethereal,eeye等)。 它的优点是可以从任何Unix内核平台上截取数据包,而不考虑什么芯片类型的网卡和驱动程序。更重要的是,它可以使开发人员编写自己的解码,显示,记录等程序。
5.2.2.1 Libpcap库主要函数
1. 头文件特征(pcap.h)
Libpcap库(数据流存储头文件 的结构定义如下图)。前半部分是数据库存储文件头的数据结构定义。
图5.5 头文件(pcap.h)定义部分截图
后半部是信息包头文件数据结构定义。
2. 打开并读取设备,设置过滤器部分
与最基层设备打交道。有三个函数:pcap_read() pcap_open_live 和 pcap_setfilter()
3. 脱机方式截取数据
及读取存储在营盘上的文件。有两个Pcap_open_offline()和Pcap_offline_read().
4. 本地网络设置检测部分
主要检测网络设置的函数有几个,包括Pcap_lookupdev() pcap_lookupnet()等。 因为前面提过,Libpcap可移植。所以各种平台的Socket借口都是兼容的。
5. 主程序
都在Pcap.c中,该文件定义了读取数据的统一接口函数pcap_next(),调用此函数获取下一个数据包。
5.4 Snort调用Libpcap
在Snort运行启动时,Snort调用Libpcap库。当调用libpcap函数并初始化接口时,进入截取数据的循环模块—pcap循环。
在这个主循环—Pcaploop(),当网卡从网络介质上接收数据开始,Pcap_loop便对采集来的每个数据包都ProcessPacket()函数处理,如果出错或达到指定的处理包数就退出。(相关代码如下)
具体就是,Pcap_loop()最后根据数据链路类型来选择数据包,然后由ProcessPacket()来进行协议分析,实施信息流的匹配。
如:ProcessPaceket函数调用DecodeEthPkt函数来对以太网数据进行解码。其中DecodeEthPkt()函数再调用子函数Decode IP来对IP协议进行解码......
Libpcap函数功能列举:
Pcap_open_live(): 获得数据包通用句柄。
Pcap_lookup_dev(): 指向网络可用设备。
Pcap_looknet(): 初步判断网络设备本身的IP & netmask。
Pcap_Dump(): 基于TCPDump的,将网络数据包保存成文件。
程序部分代码如下:
/* Read all packets on the device. Continue until cnt packets read */
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int n;
for (;
{ //for循环
if (p->sf.rfile != NULL) {
n = pcap_offline_read(p, cnt, callback, user);
} else {
// XXX keep reading until we get something
do {
n = p->read_op(p, cnt, callback, user);
} while (n == 0);
}
if (n <= 0)
return (n); //遇错误,返回
if (cnt > 0) {
cnt -= n;
if (cnt <= 0)
return (0); //达到制定数量,返回
}
}
}
pcap_loop()有几个重要参数:
参数是pv.pkt_cnt,表示总共要捕捉的包的数量。在main函数初始化时,缺省设置为-1,成为永真循环,一直捕捉直到程序退出:
/* initialize the packet counter to loop forever */
pv.pkt_cnt = -1;
或者在命令行中设置要捕捉的包的数量。ParseCmdLine函数的调用中,遇到参数n,重新设定pv.pkt_cnt的值。ParseCmdLine中相关语句如下:
case 'n': /* grab x packets and exit */
pv.pkt_cnt = atoi(optarg);
Snort.c主程序中,Pcap_loop()函数有两种提取数据模式:
打开网卡和打开文件。
/* get the device file descriptor,打开网卡接口 */
pd = pcap_open_live(pv.interface, snaplen,
pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf);
或者
/* open the file,打开文件 */
pd = pcap_open_offline(intf, errorbuf);
只有以上两种返回情况。
Snort把真实的数据包存储在内存中指针指向的数据结构中。在decode.h中,定义了所有Snort要使用到的数据结构,包括Tcp,Ip,以太桢,vlan桢等。Snort的这些结构将指针指向截获的包上来代表相应的协议。如指向以太桢用数据指针使用_EthrHdr头。
数据结构:
Typededf struct _etherhdr
{
u_int8_t ether_dst[6]; //目的地址;
u_int8_t ether_src[6]; //源地址;
u_int16_t ether_type; //协议类型;
}
typedef struct _Tcphdr
{
u_int16_t th_sport; //源端口;
u_int16_t th_dport; //目端口;
u_int32_t th_seq; //sequence number;
u_int32_t th_ack; //acknowledgement number;
u_int8_t th_offx2; //offset and reserved;
u_int8_t th_flags; //flags;
u_int16_t th_win; //window;
u_int16_t th_sum; //checksum;
u_int16_t th_urp; //urgent pointer;
}
小结
网络数据的截取是入侵检测系统的基础。本节从网络数据截取机制开始讲,讲述了常见的两种机制。重点讲述了Libpcap库的网络数据包截取机制。
网络监听攻击技术
█网络监听的原理
Ethernet(以太网,它是由施乐公司发明的一种比较流行的局域网技术,它包含一条所有计算机都连接到其上的一条电缆,每台计算机需要一种叫接口板的硬件才能连接到以太网)协议的工作方式是将要发送的数据包发往连接在一起的所有主机。在包头中包括有应该接收数据包的主机的正确地址,因为只有与数据包中目标地址一致的那台主机才能接收到信息包,但是当主机工作在监听模式下的话不管数据包中的目标物理地址是什么,主机都将可以接收到。许多局域网内有十几台甚至上百台主机是通过一个电缆、一个集线器连接在一起的,在协议的高层或者用户来看,当同一网络中的两台主机通信的时候,源主机将写有目的的主机地址的数据包直接发向目的主机,或者当网络中的一台主机同外界的主机通信时,源主机将写有目的的主机IP地址的数据包发向网关。但这种数据包并不能在协议栈的高层直接发送出去,要发送的数据包必须从TCP/IP协议的IP层交给网络接口,也就是所说的数据链路层。网络接口不会识别IP地址的。在网络接口由IP层来的带有IP地址的数据包又增加了一部分以太祯的祯头的信息。在祯头中,有两个域分别为只有网络接口才能识别的源主机和目的主机的物理地址这是一个48位的地址,这个48位的地址是与IP地址相对应的,换句话说就是一个IP地址也会对应一个物理地址。对于作为网关的主机,由于它连接了多个网络,它也就同时具备有很多个IP地址,在每个网络中它都有一个。而发向网络外的祯中继携带的就是网关的物理地址。
Ethernet中填写了物理地址的祯从网络接口中,也就是从网卡中发送出去传送到物理的线路上。如果局域网是由一条粗网或细网连接成的,那么数字信号在电缆上传输信号就能够到达线路上的每一台主机。再当使用集线器的时候,发送出去的信号到达集线器,由集线器再发向连接在集线器上的每一条线路。这样在物理线路上传输的数字信号也就能到达连接在集线器上的每个主机了。当数字信号到达一台主机的网络接口时,正常状态下网络接口对读入数据祯进行检查,如果数据祯中携带的物理地址是自己的或者物理地址是广播地址,那么就会将数据祯交给IP层软件。对于每个到达网络接口的数据祯都要进行这个过程的。但是当主机工作在监听模式下的话,所有的数据祯都将被交给上层协议软件处理。
当连接在同一条电缆或集线器上的主机被逻辑地分为几个子网的时候,那么要是有一台主机处于监听模式,它还将可以接收到发向与自己不在同一个子网(使用了不同的掩码、IP地址和网关)的主机的数据包,在同一个物理信道上传输的所有信息都可以被接收到。
在UNIX系统上,当拥有超级权限的用户要想使自己所控制的主机进入监听模式,只需要向Interface(网络接口)发送I/O控制命令,就可以使主机设置成监听模式了。而在Windows9x的系统中则不论用户是否有权限都将可以通过直接运行监听工具就可以实现了。
在网络监听时,常常要保存大量的信息(也包含很多的垃圾信息),并将对收集的信息进行大量的整理,这样就会使正在监听的机器对其它用户的请求响应变的很慢。同时监听程序在运行的时候需要消耗大量的处理器时间,如果在这个时候就详细的分析包中的内容,许多包就会来不及接收而被漏走。所以监听程序很多时候就会将监听得到的包存放在文件中等待以后分析。分析监听到的数据包是很头疼的事情。因为网络中的数据包都非常之复杂。两台主机之间连续发送和接收数据包,在监听到的结果中必然会加一些别的主机交互的数据包。监听程序将同一TCP会话的包整理到一起就相当不容易了,如果你还期望将用户详细信息整理出来就需要根据协议对包进行大量的分析。Internet上那么多的协议,运行进起的话这个监听程序将会十分的大哦。
现在网络中所使用的协议都是较早前设计的,许多协议的实现都是基于一种非常友好的,通信的双方充分信任的基础。在通常的网络环境之下,用户的信息包括口令都是以明文的方式在网上传输的,因此进行网络监听从而获得用户信息并不是一件难点事情,只要掌握有初步的TCP/IP协议知识就可以轻松的监听到你想要的信息的。前些时间美籍华人China-babble曾提出将望路监听从局域网延伸到广域网中,但这个想法很快就被否定了。如果真是这样的话我想网络必将天下大乱了。而事实上现在在广域网里也可以监听和截获到一些用户信息。只是还不够明显而已。在整个Internet中就更显得微不足道了。
下面是一些系统中的著名的监听程序,你可以自己尝试一下的。
█检测网络监听的方法
网络监听在上述中已经说明了。它是为了系统管理员管理网络,监视网络状态和数据流动而设计的。但是由于它有着截获网络数据的功能所以也是黑客所惯用的伎俩之一。
一般检测网络监听的方法通过以下来进行:
网络监听说真的,是很难被发现的。当运行监听程序的主机在进听的过程中只是被动的接收在以太网中传输的信息,它不会跟其它的主机交换信息的,也不能修改在网络中传输的信息包。这就说明了网络监听的检测是比较麻烦的事情。
一般情况下可以通过ps-ef或者ps-aux来检测。但大多实施监听程序的人都会通过修改ps的命令来防止被ps-ef的。修改ps只需要几个shell把监听程序的名称过滤掉就OK了。一能做到启动监听程序的人也绝对不是个菜的连这个都不懂的人了,除非是他懒。
上边提到过。当运行监听程序的时候主机响应一般会受到影响变的会慢,所以也就有人提出来通过响应的速率来判断是否受到监听。如果真是这样判断的话我想世界真的会大乱了,说不准一个时间段内会发现无数个监听程序在运行呢。呵呵。
如果说当你怀疑网内某太机器正在实施监听程序的话(怎么个怀疑?那要看你自己了),可以用正确的IP地址和错误的物理地址去ping它,这样正在运行的监听程序就会做出响应的。这是因为正常的机器一般不接收错误的物理地址的ping信息的。但正在进听的机器就可以接收,要是它的IP stack不再次反向检查的话就会响应的。不过这种方法对很多系统是没效果的,因为它依赖于系统的IP stack。
另一种就是向网上发大量不存在的物理地址的包,而监听程序往往就会将这些包进行处理,这样就会导致机器性能下降,你可以用icmp echo delay来判断和比较它。还可以通过搜索网内所有主机上运行的程序,但这样做其的难度可想而知,因为这样不但是大的工作量,而且还不能完全同时检查所有主机上的进程。可是如果管理员这样做也会有很大的必要性,那就是可以确定是否有一个进程是从管理员机器上启动的。
在Unix中可以通过ps -aun或ps -augx命令产生一个包括所有进程的清单:进程的属主和这些进程占用的处理器时间和内存等。这些以标准表的形式输出在STDOUT上。如果某一个进程正在运行,那么它将会列在这张清单之中。但很多黑客在运行监听程序的时候会毫不客气的把ps或其它运行中的程序修改成Trojan Horse程序,因为他完全可以做到这一点的。如果真是这样那么上述办法就不会有结果的。但这样做在一定程度上还是有所作为的。在Unix和Windows NT上很容易就能得到当前进程的清单了。但DOS、Windows9x好象很难做到哦,具体是不是我没测试过不得而知。
还有一种方式,这种方式要靠足够的运气。因为往往黑客所用的监听程序大都是免费在网上得到的,他并非专业监听。所以做为管理员用来搜索监听程序也可以检测。使用Unix可以写这么一个搜索的小工具了,不然的话要累死人的。呵呵。
有个叫Ifstatus的运行在Unix下的工具,它可以识别出网络接口是否正处于调试状态下或者是在进听装下。要是网络接口运行这样的模式之下,那么很有可能正在受到监听程序的攻击。Ifstatus一般情况下不会产生任何输出的,当它检测到网络的接口处于监听模式下的时候才回输出。管理员可以将系统的cron参数设置成定期运行Ifstatus,如果有好的cron进程的话可以将它产生的输出用mail发送给正在执行cron任务的人,要实现可以在crontab目录下加****/usr/local/etc/ifstatus一行参数。这样不行的话还可以用一个脚本程序在crontab下00****/usr/local/etc/run-ifstatus。
抵御监听其实要看哪个方面了。一般情况下监听只是对用户口令信息比较敏感一点(没有无聊的黑客去监听两台机器间的聊天信息的那是个浪费时间的事情)。所以对用户信息和口令信息进行加密是完全有必要的。防止以明文传输而被监听到。现代网络中,SSH(一种在应用环境中提供保密通信的协议)通信协议一直都被沿用,SSH所使用的端口是22,它排除了在不安全信道上通信的信息,被监听的可能性使用到了RAS算法,在授权过程结束后,所有的传输都用IDEA技术加密。但SSH并不就是完全安全的。至少现在我们可以这么大胆评论了。
█著名的Sniffer监听工具
Sniffer之所以著名,权因它在很多方面都做的很好,它可以监听到(甚至是听、看到)网上传输的所有信息。Sniffer可以是硬件也可以是软件。主要用来接收在网络上传输的信息。网络是可以运行在各种协议之下的,包括以太网Ethernet、TCP/IP、ZPX等等,也可以是集中协议的联合体系。
Sniffer是个非常之危险的东西,它可以截获口令,可以截获到本来是秘密的或者专用信道内的信息,截获到信用卡号,经济数据,E-mail等等。更加可以用来攻击与己相临的网络。
Sniffer可以使用在任何一种平台之中。而现在使用Sniffer也不可能别发现,这个足够是对网络安全的最严重的挑战。
在Sniffer中,还有"热心人"编写了它的Plugin,称为TOD杀手,可以将TCP的连接完全切断。总之Sniffer应该引起人们的重视,否则安全永远做不到最好。
缓冲区溢出攻击
路由器原理及路由协议
TCP和UDP
TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统往往使用TCP协议传输数据。
我们来做一个实验,用计算机A(安装Windows 2000
Server操作系统)从"网上邻居"上的一台计算机B拷贝大小为8,644,608字节的文件,通过状态栏右下角网卡的发送和接收指标就会发现:虽然是数据流是由计算机B流向计算机A,但是计算机A仍发送了3,456个数据包,如图2所示。这些数据包是怎样产生的呢?因为文件传输时使用了TCP/IP协议,更确切地说是使用了面向连接的TCP协议,计算机A接收数据包的时候,要向计算机B回发数据包,所以也产生了一些通信量。
如果事先用网络监视器监视网络流量,就会发现由此产生的数据流量是9,478,819字节,比文件大小多出10.96%(如图3所示),原因不仅在于数据包和帧本身占用了一些空间,而且也在于TCP协议面向连接的特性导致了一些额外的通信量的产生。
面向非连接的UDP协议
"面向非连接"就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。这与现在风行的手机短信非常相似:你在发短信的时候,只需要输入对方手机号就OK了。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!
UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用"ping"命令来测试两台主机之间TCP/IP通信是否正常,其实"ping"命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。例如,在默认状态下,一次"ping"操作发送4个数据包(如图2所示)。大家可以看到,发送的数据包数量是4包,收到的也是4包(因为对方主机收到后会发回一个确认收到的数据包)。这充分说明了UDP协议是面向非连接的协议,没有建立连接的过程。正因为UDP协议没有连接的过程,所以它的通信效果高;但也正因为如此,它的可靠性不如TCP协议高。QQ就使用UDP发消息,因此有时会出现收不到消息的情况。