网络数据包嗅探

嗅探或网络数据包嗅探是使用嗅探工具监控和捕获通过给定网络的所有数据包的过程。这是一种我们可以"窃听电话线"并了解对话的形式。它也被称为窃听,可以应用于计算机网络。

如果一组企业交换机端口处于打开状态,那么他们的一名员工就有可能嗅探到整个网络的流量。同一物理位置的任何人都可以使用以太网电缆插入网络或无线连接到该网络并嗅探总流量。

换句话说,嗅探允许您查看各种流量,包括受保护的和不受保护的流量。在适当的条件下,使用适当的协议,攻击方可能能够收集可用于进一步攻击或给网络或系统所有者造成其他问题的信息。

可以嗅探什么?

可以从网络嗅探以下敏感信息 −

  • 电子邮件流量
  • FTP 密码
  • Web 流量
  • Telnet 密码
  • 路由器配置
  • 聊天会话
  • DNS 流量

嗅探如何工作?

嗅探器通常会将系统的 NIC 转为混杂模式,以便监听其网段上传输的所有数据。

混杂模式是指以太网硬件(特别是网络接口)的独特方式网卡 (NIC),允许 NIC 接收网络上的所有流量,即使流量不是发往此 NIC。默认情况下,NIC 会忽略所有未发往它的流量,这是通过将以太网数据包的目标地址与设备的硬件地址 (MAC) 进行比较来完成的。虽然这对于网络来说非常有意义,但非混杂模式使得使用网络监控和分析软件来诊断连接问题或流量统计变得困难。

嗅探器可以通过解码数据包中封装的信息,持续监控通过 NIC 到计算机的所有流量。

嗅探类型

嗅探本质上可以是主动的,也可以是被动的。我们现在将了解不同类型的嗅探。

被动嗅探

在被动嗅探中,流量被锁定,但不会以任何方式改变。被动嗅探仅允许监听。它与 Hub 设备配合使用。在集线器设备上,流量被发送到所有端口。在使用集线器连接系统的网络中,网络上的所有主机都可以看到流量。因此,攻击者可以轻松捕获通过的流量。

好消息是,集线器在最近几乎已经过时了。大多数现代网络都使用交换机。因此,被动嗅探不再有效。

主动嗅探

在主动嗅探中,流量不仅被锁定和监控,而且还可能以某种方式根据攻击决定进行更改。主动嗅探用于嗅探基于交换机的网络。它涉及将地址解析数据包 (ARP) 注入目标网络以淹没交换机内容可寻址存储器 (CAM) 表。CAM 会跟踪哪个主机连接到哪个端口。

以下是主动嗅探技术 −

  • MAC 泛洪
  • DHCP 攻击
  • DNS 中毒
  • 欺骗攻击
  • ARP 中毒

嗅探对协议的影响

诸如久经考验的 TCP/IP之类的协议在设计时从未考虑过安全性。此类协议对潜在入侵者没有太大的抵抗力。以下是易于嗅探的不同协议 −

HTTP

它用于以明文形式发送信息,没有任何加密,因此是真正的目标。

SMTP(简单邮件传输协议)

SMTP 用于电子邮件传输。该协议非常高效,但不包括任何防嗅探保护措施。

NNTP(网络新闻传输协议)

它用于所有类型的通信。它的主要缺点是数据甚至密码都以明文形式通过网络发送。

POP(邮局协议)

POP 仅用于从服务器接收电子邮件。该协议不包括防嗅探保护措施,因为它可能被捕获。

FTP(文件传输协议)

FTP 用于发送和接收文件,但不提供任何安全功能。所有数据都以明文形式发送,因此很容易被嗅探。

IMAP(Internet 消息访问协议)

IMAP 的功能与 SMTP 相同,但极易受到嗅探。

Telnet

Telnet 通过网络以明文形式发送所有内容(用户名、密码、按键),因此很容易被嗅探。

嗅探器并不是只允许您查看实时流量的愚蠢实用程序。如果您确实想分析每个数据包,请保存捕获并在时间允许时查看它。

使用 Python 实现

在实现原始套接字嗅探器之前,让我们先了解一下下面描述的 struct 方法 −

struct.pack(fmt, a1,a2,…)

顾名思义,此方法用于返回根据给定格式打包的字符串。字符串包含值 a1、a2 等。

struct.unpack(fmt, string)

顾名思义,此方法根据给定格式解包字符串。

在下面的原始套接字嗅探器 IP 标头示例中,它是数据包中的接下来的 20 个字节,在这 20 个字节中,我们感兴趣的是最后 8 个字节。后面的字节显示源和目标 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 header。