📜  如何在Python使用 Scapy 检测 ARP 欺骗攻击?

📅  最后修改于: 2022-05-13 01:55:28.194000             🧑  作者: Mango

如何在Python使用 Scapy 检测 ARP 欺骗攻击?

ARP 欺骗也称为 ARP 中毒,它是一种网络攻击,其中恶意用户通过LAN(局域网发送伪造的 ARP(地址解析协议)消息。这会导致攻击者的 MAC 地址与网络上合法计算机或服务器的 IP 地址相关联。

在这里,我们将在收到一个 ARP 数据包后执行被动监视或扫描以嗅探网络中的数据包,有两件事需要分析,如果它们不匹配,则比较它们,则用户受到 ARP 欺骗攻击。为了欺骗和检测网络内部的 ARP 数据包,使用 Scapy 和Python在 MAC 地址和接口的帮助下执行 ARP 数据包的检测。

  • 源 MAC 地址
  • 发件人的真实 MAC 地址

什么是斯皮?

Scapy是一种用于计算机网络的数据包操作工具,最初是用Python编写的。它可以伪造或解码数据包,通过网络发送它们,捕获它们,并匹配请求和回复。它还可以处理扫描、跟踪路由、探测、单元测试、攻击和网络发现等任务。它在 Linux、macOS 和 Windows 上运行,但最新版本的 Scapy 支持 Windows 开箱即用,因此也可以在 Windows 机器上使用 Scapy 的所有功能。 Scapy 可以执行以下操作

  • 制作任何数据包并对其进行编码
  • 嗅探网络数据包
  • 发送有效/无效帧
  • 注入你自己的 802.11 帧
  • 编辑网络数据包
  • 扫描网络
  • 跟踪和探测
  • 攻击网络和网络发现。

Scapy 安装

要安装 Scapy,您必须安装Python 2.7 或Python 3.9+ 版本。如果未安装,请参阅此Python安装。为防止中间人使用动态 ARP 检测,该安全功能将自动拒绝将检测到的恶意 ARP 数据包。

Linux

对于 Linux 用户,可以在没有 libcap 的情况下运行 scapy。



  • 安装tcpdump并确保它在$PATH 中
$ sudo apt-get tcpdump
  • 内核必须选择数据包套接字 – CONFIG_PACKET
  • 如果内核小于 2.6,请确保选择了 Socket Filtering – CONFIG_FILTER

在 Linux 上安装 Scapy 的另一种方法是在 Linux 机器上安装Python ,然后在Python Shell 中安装 Scapy 包。

$ sudo apt-get install python3

终端安装好Python后,打开Python shell,执行命令安装scapy,然后使用scapy进行ARP欺骗检测,打开Scapy编写代码,进行网络内部数据包的欺骗检测,

$ sudo apt-get install scapy (OR)
$ python -m install scapy
$ python
>> scapy

Debian/Fedora/Ubuntu

# Debian
$ sudo apt-get install tcpdump

# Fedora 
$ yum install tcpdmp

然后通过 pip 或 apt 安装 Scapy。所有依赖项都可以通过特定于平台的安装程序或通过 PyPI 安装

视窗

要在 Windows 上安装 scapy,可以通过命令提示符轻松完成,但对于 Windows,还应在系统上预安装Python 。然后将执行安装scapy的命令。

C:\> python -m install python-scapy
C:\> python
>> scapy

现在让我们在Python使用 Scapy 启动 ARP 欺骗攻击检测

使用 Scapy 进行 ARP 欺骗攻击检测

现在我们已经在系统上成功安装了Python和 scapy,让我们继续从 scapy 导入必要的库。

Python3
# importing libraries form scapy
from scapy.all import Ether, ARP, srp, sniff, conf
import scapy as scapy
  
# to import all libraries from scapy
# irrespective of which one to use execute the code
from scapy.all import *


Python3
# importing all libraries of scapy
import scapy.all as scapy
  
# taking interface of the system as an argument
# to sniff packets inside the network
def sniff(interface):
    # store=False tells sniff() function to discard sniffed packets
    scapy.sniff(iface=interface, store=False, prn=process_sniffed_packet)
  
  
def process_sniffed_packet(packet):
  # if it is an ARP Packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
        print(packet.show())
  
  
# machine interface is "eth0", sniffing the interface
sniff("eth0")


Python3
# code to get MAC Address
def mac(ipadd):
  # requesting arp packets from the IP address 
  # if it's wrong then will throw error
    arp_request = scapy.ARP(pdst=ipadd)
    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_req_br = br / arp_request
    list_1 = scapy.srp(arp_req_br, timeout=5, 
                       verbose=False)[0]
    return list_1[0][1].hwsrc
  
# defining function to process sniffed packet
def process_sniffed_packet(packet):
  # if it is an ARP packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
  
       # originalmac will get old MAC whereas
        originalmac = mac(packet[scapy.ARP].psrc)
        # responsemac will get response of the MAC
        responsemac = packet[scapy.ARP].hwsrc


Python3
# comparing values of real MAC Address and response MAC Address
if originalmac != responsemac:
    print("[*] ALERT!!! You are under attack, ARP table is being poisoned.!")


Python3
# Implementing ARP Spoof Attack Detection Using Scapy
  
# import modules
import scapy.all as scapy
  
  
# code to get MAC Address
def mac(ipadd):
  # requesting arp packets from the IP address
  # if it's wrong then will throw error
    arp_request = scapy.ARP(pdst=ipadd)
    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_req_br = br / arp_request
    list_1 = scapy.srp(arp_req_br, timeout=5,
                       verbose=False)[0]
    return list_1[0][1].hwsrc
  
# taking interface of the system as an argument
# to sniff packets inside the network
def sniff(interface):
    # store=False tells sniff() function 
    # to discard sniffed packets
    scapy.sniff(iface=interface, store=False, 
                prn=process_sniffed_packet)
  
  
# defining function to process sniffed packet
def process_sniffed_packet(packet):
  # if it is an ARP packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
  
       # originalmac will get old MAC whereas
        originalmac = mac(packet[scapy.ARP].psrc)
        # responsemac will get response of the MAC
        responsemac = packet[scapy.ARP].hwsrc
  
  
# machine interface is "eth0", sniffing the interface
sniff("eth0")


该程序将检测是否有任何类型的数据包具有欺骗性 ARP 层,以便执行代码。 sniff()函数回调应用于每个将被嗅探的数据包。在store=False 告诉 sniff()函数丢弃嗅探的数据包而不是将它们存储在内存中,这在脚本运行很长时间时很有用。

Use this code to check the interface of the machine you want to sniff
>> conf.iface

蟒蛇3

# importing all libraries of scapy
import scapy.all as scapy
  
# taking interface of the system as an argument
# to sniff packets inside the network
def sniff(interface):
    # store=False tells sniff() function to discard sniffed packets
    scapy.sniff(iface=interface, store=False, prn=process_sniffed_packet)
  
  
def process_sniffed_packet(packet):
  # if it is an ARP Packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
        print(packet.show())
  
  
# machine interface is "eth0", sniffing the interface
sniff("eth0")

嗅探到eth0接口后会显示接口的内容,这里我们看到接口是以太网,其相关内容显示为IP Destination(dst), type of interface(ARP), source(src)

使用 ARP函数创建一个给定 IP 地址的函数mac以创建/创建 ARP 请求arp_request并检索实际 MAC 地址而不是 IP 地址。使用以太函数将广播 MAC 地址设置为“ff:ff:ff:ff:ff:ff”srp函数返回两个响应数据包的 IP 地址列表。具有所请求的匹配 IP 地址的 MAC 地址将存储在hwsrc字段中。

将创建一个函数来获取 MAC 地址并处理嗅探的数据包,获取“originalmac”变量中旧 MAC 的值和响应中 MAC 值作为“ repsonsemac”变量。 Scapy 在字段“op”中对 ARP 数据包类型进行编码以进行操作,默认情况下 op 为 1 或“who-has” ,这是一个 ARP 请求。

蟒蛇3

# code to get MAC Address
def mac(ipadd):
  # requesting arp packets from the IP address 
  # if it's wrong then will throw error
    arp_request = scapy.ARP(pdst=ipadd)
    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_req_br = br / arp_request
    list_1 = scapy.srp(arp_req_br, timeout=5, 
                       verbose=False)[0]
    return list_1[0][1].hwsrc
  
# defining function to process sniffed packet
def process_sniffed_packet(packet):
  # if it is an ARP packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
  
       # originalmac will get old MAC whereas
        originalmac = mac(packet[scapy.ARP].psrc)
        # responsemac will get response of the MAC
        responsemac = packet[scapy.ARP].hwsrc

现在比较这两个值并检查它们是否相似,以防它们不相似,则这意味着这些值已被欺骗。比较的值是实际 MAC 地址和响应 MAC 地址。

蟒蛇3

# comparing values of real MAC Address and response MAC Address
if originalmac != responsemac:
    print("[*] ALERT!!! You are under attack, ARP table is being poisoned.!")

以下是完整代码

蟒蛇3

# Implementing ARP Spoof Attack Detection Using Scapy
  
# import modules
import scapy.all as scapy
  
  
# code to get MAC Address
def mac(ipadd):
  # requesting arp packets from the IP address
  # if it's wrong then will throw error
    arp_request = scapy.ARP(pdst=ipadd)
    br = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_req_br = br / arp_request
    list_1 = scapy.srp(arp_req_br, timeout=5,
                       verbose=False)[0]
    return list_1[0][1].hwsrc
  
# taking interface of the system as an argument
# to sniff packets inside the network
def sniff(interface):
    # store=False tells sniff() function 
    # to discard sniffed packets
    scapy.sniff(iface=interface, store=False, 
                prn=process_sniffed_packet)
  
  
# defining function to process sniffed packet
def process_sniffed_packet(packet):
  # if it is an ARP packet and if it is an ARP Response
    if packet.haslayer(scapy.ARP) and packet[scapy.ARP].op == 2:
  
       # originalmac will get old MAC whereas
        originalmac = mac(packet[scapy.ARP].psrc)
        # responsemac will get response of the MAC
        responsemac = packet[scapy.ARP].hwsrc
  
  
# machine interface is "eth0", sniffing the interface
sniff("eth0")

输出: