网络数据包嗅探
嗅探或网络数据包嗅探是指使用嗅探工具监控和捕获通过给定网络的所有数据包的过程。这是一种我们可以“窃听电话线”并了解对话的方式。它也称为窃听,可以应用于计算机网络。
如果企业交换机端口开启,则其员工之一可能会嗅探整个网络流量,这种可能性非常大。任何在同一物理位置的人都可以使用以太网电缆连接到网络或无线连接到该网络并嗅探全部流量。
换句话说,嗅探允许您查看各种流量,包括受保护的和不受保护的流量。在适当的条件下并实施适当的协议,攻击方可能会收集信息,这些信息可用于进一步攻击或为网络或系统所有者造成其他问题。
可以嗅探什么?
可以从网络中嗅探以下敏感信息:
- 电子邮件流量
- FTP密码
- Web流量
- Telnet密码
- 路由器配置
- 聊天会话
- DNS流量
嗅探是如何工作的?
嗅探器通常将系统的NIC切换到混杂模式,以便它监听在其段上传输的所有数据。
混杂模式是指以太网硬件(特别是网络接口卡 (NIC))的独特方式,它允许NIC接收网络上的所有流量,即使这些流量并非发往此NIC。默认情况下,NIC会忽略所有未发往它的流量,这是通过将以太网数据包的目标地址与其设备的硬件地址 (MAC) 进行比较来实现的。虽然这对于网络来说非常有意义,但非混杂模式使得难以使用网络监控和分析软件来诊断连接问题或进行流量统计。
嗅探器可以通过解码数据包中封装的信息,持续监控通过NIC传输到计算机的所有流量。
嗅探类型
嗅探可以是主动的,也可以是被动的。我们现在将学习不同类型的嗅探。
被动嗅探
在被动嗅探中,流量被捕获,但不会以任何方式被更改。被动嗅探只允许监听。它与集线器设备一起使用。在集线器设备上,流量被发送到所有端口。在使用集线器连接系统的网络中,网络上的所有主机都可以看到流量。因此,攻击者可以轻松捕获通过的流量。
好消息是集线器近来已几乎淘汰。大多数现代网络使用交换机。因此,被动嗅探不再有效。
主动嗅探
在主动嗅探中,流量不仅被捕获和监控,而且还可能以攻击所确定的某种方式被更改。主动嗅探用于嗅探基于交换机的网络。它涉及将地址解析协议 (ARP) 数据包注入目标网络,以泛滥交换机的內容寻址記憶體 (CAM) 表。CAM 跟踪哪个主机连接到哪个端口。
以下是主动嗅探技术:
- MAC泛洪
- DHCP攻击
- DNS欺骗
- 欺骗攻击
- ARP欺骗
嗅探对协议的影响
诸如久经考验的TCP/IP之类的协议在设计时并未考虑安全性。此类协议对潜在入侵者几乎没有抵抗力。以下是易于嗅探的不同协议:
HTTP
它用于以明文形式发送信息,没有任何加密,因此是一个真正的目标。
SMTP(简单邮件传输协议)
SMTP用于传输电子邮件。该协议高效,但不包含任何防嗅探保护。
NNTP(网络新闻传输协议)
它用于所有类型的通信。其主要缺点是数据甚至密码都以明文形式通过网络发送。
POP(邮局协议)
POP严格用于从服务器接收电子邮件。该协议不包含防嗅探保护,因为它可以被拦截。
FTP(文件传输协议)
FTP用于发送和接收文件,但它不提供任何安全功能。所有数据都以明文形式发送,很容易被嗅探。
IMAP(互联网消息访问协议)
IMAP的功能与SMTP相同,但它极易受到嗅探。
Telnet
Telnet 将所有内容(用户名、密码、击键)以明文形式通过网络发送,因此很容易被嗅探。
嗅探器并非只能查看实时流量的简单实用程序。如果您真的想分析每个数据包,请保存捕获的内容并在有时间时查看。
使用 Python 实现
在实现原始套接字嗅探器之前,让我们了解如下所述的struct方法:
struct.pack(fmt, a1,a2,…)
顾名思义,此方法用于返回根据给定格式打包的字符串。字符串包含值 a1、a2 等。
struct.unpack(fmt, string)
顾名思义,此方法根据给定格式解包字符串。
在以下原始套接字嗅探器 IP 报头示例中,它是数据包中的接下来的 20 个字节,在这 20 个字节中,我们只关注最后 8 个字节。后面的字节显示源 IP 地址和目标 IP 地址是否正在解析:
现在,我们需要导入一些基本的模块,如下所示:
import socket import struct import binascii
现在,我们将创建一个套接字,它将具有三个参数。第一个参数告诉我们数据包接口——针对 Linux 的 PF_PACKET 和针对 Windows 的 AF_INET;第二个参数告诉我们它是一个原始套接字;第三个参数告诉我们我们感兴趣的协议——0x0800 用于 IP 协议。
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket. htons(0x0800))
现在,我们需要调用recvfrom()方法来接收数据包。
while True: packet = s.recvfrom(2048)
在下面的代码行中,我们正在剥离以太网报头:
ethernet_header = packet[0][0:14]
使用下面的代码行,我们使用struct方法解析和解包报头:
eth_header = struct.unpack("!6s6s2s", ethernet_header)
下面的代码行将返回一个包含三个十六进制值的元组,这些值由binascii模块中的hexify转换:
print "Destination MAC:" + binascii.hexlify(eth_header[0]) + " Source MAC:" + binascii.hexlify(eth_header[1]) + " Type:" + binascii.hexlify(eth_header[2])
我们现在可以通过执行下面的代码行来获取 IP 报头:
ipheader = pkt[0][14:34] ip_header = struct.unpack("!12s4s4s", ipheader) print "Source IP:" + socket.inet_ntoa(ip_header[1]) + " Destination IP:" + socket.inet_ntoa(ip_header[2])
同样,我们也可以解析 TCP 报头。