Section outline

  •        数据包嗅探和伪造是网络安全中两个重要的概念,它们是网络通信中的两大威胁。能够理解这些威胁对于了解网络中的安全措施至关重要。有许多嗅探和伪造工具,如 Wireshark, Tcpdump, Scapy 等等。这些工具被安全专家以及攻击者广泛使用。能够使用这些工具固然重要,但更为重要的是了解这些工具是如何工作的,即在软件中如何实现嗅探和伪造。这个实验的目的有两方面:其一是学习使用这些工具并理解这些工具背后的技术;其二,学生们将编写简单的嗅探和伪造程序,并深入理解这些程序的技术方面。本实验涵盖以下主题:
    • 数据包嗅探和伪造的工作原理
    • 使用 Scapy 进行包嗅探
    • 使用 Scapy 进行数据包伪造
    • 把 zip 文件下载到 VM 里, 然后用 unzip 命令解压缩。

    • Wireshark 是最常用的嗅探工具,且易于使用。在整个实验中我们将使用它。但是作为构建其他工具的基础模块, Wireshark 却很难胜任这一点。我们将使用 Scapy 来完成这一任务。这个任务的目标是学习如何在 Python 程序中使用 Scapy 进行包嗅探。以下提供了一个示例代码:
      #!/usr/bin/env python3
      from scapy.all import *
      
      def print_pkt(pkt):
        pkt.show()
      
      pkt = sniff(iface='br-c93733e9f913', filter='icmp', prn=print_pkt)
      上述代码将在 br-c93733e9f913 接口上嗅探数据包。请参阅实验环境设置部分的说明来获取正确的接口名称。如果要同时在多个接口上嗅探包,可以将这些接口放入一个列表,并将其分配给 iface 变量。以下是一个例子:
       
      iface=['br-c93733e9f913', 'enp0s3']
        • 在上述程序中,对于捕获的每个包,回调函数 print_pkt() 将被调用,这个函数将打印一些关于该包的信息。请使用 root 权限运行程序并演示你确实可以捕获到包。然后再次运行程序,但不使用 root 权限,描述和解释你的观察结果。

          // 使程序可执行
          # chmod a+x sniffer.py
          
          // 使用 root 权限运行程序
          # sniffer.py
          
          // 切换到 seed 账号,
          // 不使用 root 权限再次运行程序
          # su seed
          $ sniffer.py
          
        • 通常,当我们嗅探包时,我们只对某些类型的包感兴趣。可以通过设置嗅探过滤器来实现这一点。Scapy 的过滤器使用 Berkeley Packet Filter (BPF) 语法,可以从互联网上找到 BPF 手册。请设置以下过滤器并再次演示你的嗅探程序(每个过滤器应单独设置):
          • 只捕获 ICMP 包;
          • 捕获来自某个特定 IP 地址并且目标端口号为 23 的 TCP 包;
          • 捕获来自或去往某个特定网络的包。可以选择任意网络,例如128.230.0.0/16,但不应选择与你的虚拟机连接的同一子网。
    • 作为包伪造工具,Scapy 允许我们在 IP 包各字段设置任意值。这个任务的目标在伪造的数据包里设置任意源 IP 地址。我们伪造 ICMP echo 请求包,并将它们发送到同一网络中的一台主机。我们将使用Wireshark 来观察接收者是否接受了我们的请求。以下代码展示了如何伪造 ICMP 数据包。
      >>> from scapy.all import *
      >>> a = IP()              // 行 1
      >>> a.dst = '10.0.2.3'    // 行 2
      >>> b = ICMP()            // 行 3
      >>> p = a/b               // 行 4
      >>> send(p)               // 行 5
      .
      Sent 1 packets.
      在上述代码中,行 1 创建了一个 IP 对象,每个 IP 头部字段都有一个类属性。我们可以使用 a 或 ls(IP) 来查看所有属性名称和它们的值。我们也可以用 a.show() 和 IP.show() 来做同样的事情。行 2 显示了如何设置目标 IP 地址字段。如果某个字段未被设置,则会使用默认值。
      >>> ls(a)
      version    : BitField (4 bits)       = 4               (4)
      ihl        : BitField (4 bits)       = None            (None)
      tos        : XByteField              = 0               (0)
      len        : ShortField              = None            (None)
      id         : ShortField              = 1               (1)
      flags      : FlagsField (3 bits)     = <Flag 0 ()>     (<Flag 0 ()>)
      frag       : BitField (13 bits)      = 0               (0)
      ttl        : ByteField               = 64              (64)
      proto      : ByteEnumField           = 0               (0)
      chksum     : XShortField             = None            (None)
      src        : SourceIPField           = '127.0.0.1'     (None)
      dst        : DestIPField             = '127.0.0.1'     (None)
      options    : PacketListField         = []              ([])
      行 3 创建了一个 ICMP 对象。默认类型是 echo 请求。在 行 4 中,我们将 a 和 b 相结合以形成一个新的对象。/ 操作符被 IP 类重载,因此它不再表示除法,而是意味着将 b 作为 a 的负载字段并相应地修改 a 的字段。结果我们得到了一个代表 ICMP 包的新对象。我们现在可以使用 行 5 的 send() 发送这个包。请根据示例代码做出必要的更改,并演示你能够伪造 ICMP  echo 请求包。
    • 本任务的目标是使用 Scapy 来估计从你的虚拟机到目标的距离,即这之间隔着多少个路由器,这其实就是 traceroute 工具所做的事情。在本任务中,我们将编写自己的工具,实现的办法也较简单。首先,我们向目的地发送一个 IP 数据包(可以是任何类型),将它的生存时间(TTL)字段设置为1。这个包将在第一个路由器处被丢弃,并返回一个 ICMP 错误消息,告诉我们生存时间已经超时。这就是我们获得第一个路由器的 IP 地址的方式。然后我们将 TTL 字段增加到 2,再次发送数据包,这次这个包可以到达第二个路由器,才会被丢弃,我们因此可以获取第二个路由器的 IP 地址。我们将重复此过程直到最终我们的包到达目的地。
       
      需要注意的是,这个实验仅能获得估计结果,因为在理论上,这些包不一定沿着相同的路径行进(但在实践中,在短时间内包走的路径大概率是相同的)。以下代码展示了该过程的一个回合。
      a = IP()
      a.dst = '1.2.3.4'
      a.ttl = 3
      b = ICMP()
      send(a/b)
      如果你是一个经验较丰富的 Python 程序员,你可以编写一个工具自动完成整个过程。如果你对 Python 编程还是是新手,可以通过手动更改每个回合的 TTL 字段并用 Wireshark 获得返回的 ICMP 包。无论哪一种方式都可以接受,只要你能得到结果即可。
    • 在本任务中,我们将结合使用窃听和伪造技术。我们需要在同一局域网上的两台机器,虚拟机(VM)和用户容器。从用户容器上, ping 一个 IP 地址 X,这会生成一个 ICMP echo 请求数据包。如果目标 X 是在线的,那么 ping 程序将接收到 echo 回复,并打印出响应。你的程序在虚拟机上运行,通过数据包嗅探监控局域网。每当看到一个 ICMP echo 请求时(不论目标 IP 地址是什么),它立即使用数据包伪造技术发送 echo 回复。因此,无论机器 X 是否是在线的, ping 程序都会接收到回复。你需要使用 Scapy 来完成此任务。在报告中,请提供证据以证明你的程序是成功的。

      在实验过程中,在用户容器上 ping 以下三个 IP 地址,报告并解释观察到的结果。
      ping 1.2.3.4     # 互联网上的一个不存在的主机
      ping 10.9.0.99   # 当前局域网上的一个不存在的主机
      ping 8.8.8.8     # 互联网上的一个存在的主机
  • 你需要提交一份带有截图的详细实验报告来描述你所做的工作和你观察到的现象。你还需要对一些有趣或令人惊讶的观察结果进行解释。请同时列出重要的代码段并附上解释。只是简单地附上代码不加以解释不会获得学分。实验报告的提交方式会由你的老师进行具体安排。