一、实验目的
本次实验主要是对数据包的进行嗅探和伪造。首先,众所周知数据包嗅探和伪造是网络安全的两个重要概念:它们是网络通信中的两大威胁。理解这两种威胁对于理解网络中的安全措施至关重要。有许多数据包嗅探和伪造工具,如Wireshark,Tcpdump,Netwox,Scapy等,其中一些工具被安全专家以及攻击者广泛使用。能够使用这些工具对我们来讲很重要,更重要的是了解这些工具是如何工作的,即在软件中如何实现数据包嗅探和伪造。 此次实验的目标是双重的:学习使用工具和了解这些工具背后的技术。对于第二个目标,我们将会编写简单的嗅探器和伪造/欺骗程序,并深入了解这些方面的程序和技术。此次实验涵盖以下主题: 嗅探和伪造如何工作使用pcap库和Scapy进行数据包嗅探 使用原始(raw) socket和Scapy进行数据包伪造使用 Scapy 操纵数据包。
二、实验环境
该实验已在SEED Ubuntu 20.04 VM上进行了测试。您可以从 SEED 网站下载VM影像,并在自己的计算机上运行 SEED VM。此外,大多数 SEED 实验都可以在云上进行,您也可以按照我们的指示在云上创建SEED VM。
- 实验设置文件
实验设置文件下载:Labsetup.zip 请下载实验设置文件Labsetup.zip到你的SEED VM中,并解压,然后进入解压目录中,使用下面介绍 的dcbuild命令构建初始的实验环境。 在本实验中,我们将生成公钥证书,然后使用它们来保护 Web 服务器。 证书生成任务将在虚拟机上执行, 但是我们将使用容器托管 Web 服务器。
- 使用容器的环境设置
在这个实验中,我们将使用两台连接到同一局域网的机器。我们可以使用两个VM或使用两个容器。图 1 使 用容器描绘实验环境设置。我们将对攻击容器进行所有攻击,同时使用其他容器作为用户机器。
- 容器安装及其命令
容器安装及其命令 请从实验的网站下载Labsetup.zip文件到你的虚拟机中并解压它, 进入Labsetup文件夹, 然后 用docker-compose.yml文件安装实验环境。
在下面,我们列出了一些与 Docker 和 Compose 相关的常用命令。由于我们将非常频繁地使用这些命令, 因此我们在 .bashrc文件(在我们提供的 SEEDUbuntu 20.04 虚拟机中)中为它们创建了别名。
$ docker-compose build # Build the container image
$ docker-compose up # Start the container
$ docker-compose down # Shut down the container // Aliases for the Compose commands above
$ dcbuild # Alias for: docker-compose build
$ dcup # Alias for: docker-compose up
$ dcdown # Alias for: docker-compose down
所有容器都在后台运行。 要在容器上运行命令,我们通常需要获得容器里的shell。 首先需要使用docker ps命令找出容器的 ID , 然后使用docker exec 在该容器上启动 shell 。 我们已经在.bashrc文件中为这 两个命令创建了别名。
$ dockps // Alias for: docker ps --format "{{.ID}} {{.Names}}"
$ docksh // Alias for: docker exec -it /bin/bash // The following example shows how to get a shell inside hostC
$ dockps b1004832e275
hostA-10.9.0.5 0af4ea7a3e2e
hostB-10.9.0.6 9652715c8e0a
hostC-10.9.0.7
$ docksh
96 root@9652715c8e0a:/# // Note: If a docker command requires a container ID, you do not need to // type the entire ID string. Typing the first few characters will // be sufficient, as long as they are unique among all the containers.
如果在设置实验环境时遇到问题,可以尝试从手册的"Miscellaneous Problems"部分中寻找解决方案.
- 关于攻击者容器
在这个实验中,我们可以使用 VM 或攻击者容器作为攻击机。如果您查看 Docker Compose文件,您将看 到攻击者容器的配置与其他容器的配置不同。以下是区别:
共享文件夹
当我们使用攻击容器发动攻击时,我们需要将攻击代码放入攻击容器中。代码编辑在 VM 内部比在容器中 更方便,因为我们可以使用我们最喜欢的编辑器。为了让 VM 和容器共享文件,我们使用 Docker volumes在 VM 和容器之间创建了一个共享文件夹。如果你看看Docker Compose文件,你会发现我们已经 添加了以下条目到一些容器。它表示将主机(即 VM)上的 ./volumes安装到容器内的/volumes中。我们将 在./volumes(VM 上)中编写代码,以便它们可以在容器内使用。
volumes: - ./volumes:/volumes
主机模式
在这个实验中,攻击者需要能够嗅到数据包,但是在容器内运行嗅探程序有问题,因为容器为了提高效率, 是连接到虚拟交换机上的,因此它只能看到自己的流量,而且它永远不会看到其他容器中的数据包。为了 解决这个问题,我们将攻击容器的网络模式改为使用 主机 模式,这允许攻击者容器可以查看所有流量。 攻击者容器上使用了以下条目配置来实现该功能:
network_mode: host
当容器的网络模式处于 主机 模式时,它会看到主机的所有网络接口,甚至具有与主机相同的 IP 地址。基本上,它与主机VM被放在相同的网络命名空间中。 但是,容器仍然是一个单独的机器,因为它的其他名称空间仍然不同于主机。
获取网络接口名称
当我们使用提供的"Compose"文件为该实验创建容器时,将创建一个新的网络来连接VM和容器。此网络 的 IP 前缀为 10.9.0.0/24,这在docker-compose.yml文件中已指定。分配给我们的 VM 的 IP 地址为 10.9.0.1。 我们需要在我们的 VM 上找到相应的网络接口的名称,因为我们需要在程序中使用它。网络接口名称 是Docker创建的网络的 br- 和ID 的串联。当我们使用ifconfig列出网络接口时,我们将看到相当多的接口。 查找 IP 地址 10.9.0.1。
$ ifconfig
br-c93733e9f913: flags=4163 mtu 1500 inet 10.9.0.1
netmask 255.255.255.0 broadcast 10.9.0.255
获得网络接口名称的另一种方法是使用 " docker network " 命令自行查找网络 ID(网络名称为 seed-net):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE a82477ae4e6b bridge bridge local e99b370eb525 host host local df62c6635eae none null local c93733e9f913 seed-net bridge local
由以上内容我们可以看到,共有三个容器被启动,所以在后面的实验中,我们需要区分我们进行操作以及执行相关命令是在哪一个容器或者是否是在虚拟机本机中:
在此处我们进行的文件夹的切换操作,此时依旧是在虚拟机中进行操作。
此处我们打开了一个新的命令框,同时查看并启动了容器,而后我们选择的是attacker即攻击者容器中进行操作。然后我们在执行ifconfig命令,查看attackers的接口名称即br之后的内容,我们可以看到其余外部的即之前的接口名称相同,意味着接口是共享的。
三、实验内容
任务 1: 嗅探数据包
任务 2: 伪造ICMP数据包
任务 3: Traceroute
任务 4: 嗅探和伪造
四、实验步骤
使用 Scapy 嗅探和伪造数据包
许多工具可用于嗅探和伪造,但大多数工具只提供固定功能。 Scapy 是不同的:它不仅可以用作工具,还可以用作构建其他嗅探和伪造工具的构建基块,即我们可以将 Scapy 功能集成到我们自己的程序中。在这组任务中,我们将使用 Scapy 执行每项任务。 要使用 Scapy,我们可以编写 Python 程序,然后使用 Python 执行此程序。请参阅以下示例。我们应该使 用root特权运行 Python, 因为伪造数据包需要特权。在程序的开始(行➀),我们应该导入所有的Scapy 模块。
view mycode.py
#!/usr/bin/env python3
from scapy.all import * ➀
a = IP()
- show()
此处执行时,我们是利用了gedit进行的编辑,并且是在Python环境下进行的编译,由上图可以看出,文件运行后,会显示一个IP包的相关信息。由于我们需要不断地个更改和编译Python文件,所以我们利用了后续的相关命令对文件的编译运行相关权限进行了一步的更改,是的Python文件运行时能够更加方便、快捷。
python3 mycode.py
version = 4
// Make mycode.py executable (another way to run python programs)
chmod a+x mycode.py
mycode.p
由图我们可以看出,通过执行相关的命令,更改了Python 文件的读写运行权限。
此时我们可以看到,在更改相关权限后,直接输入文件名,文件即可运行。
当然,因为volumes文件夹是共享文件夹,故而在虚拟机中更改后,在attackers容器中也可以进行文件名输入而后运行。
我们还可以进入 Python 的交互模式,然后在 Python 提示下一次运行一行我们的程序。如果我们需要在实验中频繁更改代码,则更方便。
python3
>>> from scapy.all import *
>>> a = IP()
>>> a.show()
###[ IP ]###
version = 4
ihl = None
任务 1: 嗅探数据包
Wireshark是最流行的嗅探工具,它很容易使用。我们将在整个实验中使用它。 但是,很难使用 Wireshark 作为构建其他工具的构建基块。我们将为此目的使用 Scapy。此任务的目标是 学习如何使用 Scapy 在 Python 程序中执行数据包嗅探。提供以下示例代码: #!/usr/bin/env python3
from scapy.all import *
def print_pkt(pkt):
pkt.show()
pkt = sniff(iface=' br-760f88b7d7d7', filter='icmp', prn=print_pkt)
上面的代码将嗅到 br-760f88b7d7d7 接口上的数据包。请阅读实验设置部分中有关如何获取网络接口名称 的说明。如果我们想嗅到多个接口,我们可以把所有的网络接口放在一个列表中,并把它分配给 iface。以下为示例:
iface = "br-760f88b7d7d7", "enp0s3"
当我们 执行ping 10.9.0.5时,在attackers容器中运行上述代码,可以得到对icmp包的捕获。
**任务 1.1A.**在上述程序中,对于每个捕获的数据包,回调函数print_pkt()将被调用,此函数将打印出有关 该数据包的一些信息。使用root特权运行程序,并证明你确实可以捕获数据包之后,再次运行程序,但不使用root特权:
// Make the program executable
chmod a+x sniffer.py
// Run the program with the root privilege
sniffer.py
// Switch to the "seed" account, and
// run the program without the root privilege
su seed
$ sniffer.p
由上图可以看出,我们在su seed 即普通用户权限下运行该文件时,文件无法执行。
任务 1.1B。 通常,当我们嗅到数据包时,我们只对某些类型的数据包感兴趣。我们可以通过在嗅探中设置 过滤器来做到这一点。Scapy的过滤器使用 BPF(伯克利Berkeley数据包过滤器)语法;你可以从互联网上找 到 BPF 手册。请设置以下过滤器并再次演示您的嗅探程序(每个过滤器应单独设置):
· 仅捕获 ICMP 数据包
此处上述过程中已经实现
·捕获来自特定 IP 和目的地端口 23 的任何 TCP 数据包(fiflter='host xxx.xxx.xxx.xxx').
在此处,我们执行了Telnet 10.9.0.6命令,可以看到我们在执行以及登录期间,attackers容器始终在捕获相关的数据包,我们可以对相关的TCP数据包进行分析,此中可能会得到我们的登录名seed和密码dees.
捕获数据包来自或转到的特定子网。您可以选择任何子网,如 128.230.0.0/16:您不应选择 VM 连接 到的子网。
通过实验,改变响应的子网号和端口号,我们再执行的时候,未发现对任何数据包的捕获。
任务2伪造 ICMP 数据包
作为数据包伪造工具,Scapy 允许我们将 IP 数据包的字段设置为任意值。此任务的目的是用任意源 IP 地址伪造 IP 数据包。我们将伪造 ICMP echo(回声)请求数据包,并将它们发送到同一网络上的另一个 VM。我们将使用 Wireshark 来观察接收方是否会接受我们的请求。如果接受,将发送echo(回声)回复数据包到伪造的 IP 地址。以下代码显示了如何伪造 ICMP 数据包的示例。
|------------------------------------------------------------------------------------------------------------------------------------------------------|
| >>> from scapy.all import * >>> a = IP() ➀ >>> a.dst = '10.0.2.3' ② >>> b = ICMP() ③ >>> p = a/b ④ >>> send(p) ⑤ . Sent 1 packets |
在上面的代码中,Line➀创建来自 IP 类的 IP 对象;每个 IP 标题字段都定义了一个类属性。我们可以使用 ls (a) 或 ls (IP) 查看所有属性名称/值。我们也可以使用 a.show () 和 IP.show () 来做同样的事。行②显示如何设置目的地 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 = [] ([])
行③创建 ICMP 对象。默认类型是echo(回声)请求。在行④中,我们将a和 b堆叠在一起以形成一个新的对象。/操作员被 IP 类超载,因此它不再代表除法;相反,它意味着添加b作为a 的有效载荷字段,并相应地修改该字段的字段。因此,我们得到一个代表 ICMP 数据包的新对象。我们现在可以发送此数据包使用send() (行 ⑤)。请对示例代码进行任何必要的更改,然后证明您可以使用任意源 IP 地址伪造 ICMP echo(回声)请求数据包。
任务 3: Traceroute
此任务的目标是使用 Scapy 来估计 VM 和选定目的地之间的路由器数量。这基本上是由 Traceroute 工具实现的。在这项任务中,我们将编写我们自己的工具。这个想法很简单:只需将一个数据包(任何类型)发送到目的地,其Time-To-Live (TTL) 字段将设置为 1 个。此数据包将由第一个路由器丢弃,该路由器将向我们发送 ICMP 错误消息,告诉我们已超过time-to-live。这样我们就获得了第一个路由器的 IP 地址。然后,我们将 TTL 字段增加到 2,发送另一个数据包,并获取第二路由器的 IP 地址。我们将重复此过程,直到我们的数据包最终到达目的地。
应当指出,这个实验只得到一个估计的结果,因为从理论上讲,并不是所有的这些数据包都走同样的路线
(但在实践中,他们可能在短时间内)。下面的代码显示程序中的一轮。
|-----------------------------------------------------------|
| a = IP() a.dst = '1.2.3.4' a.ttl = 3 b = ICMP() send(a/b) |
| |
执行上面的Python命令,并且在wireshark中可以捕获相关数据,如上图所示。
任务 4: 嗅探和伪造
在这项任务中,您将结合嗅探和伪造技术,实施以下嗅探和伪造程序。我们需要在同一局域网上使用两台机器:VM 和用户容器。从用户容器中,我们进行ping IP X操作。这将生成 ICMP echo(回声)请求数据包。如果 X 存活(alive),ping 程序将收到echo(回声)回复,并打印出响应。我们的嗅探和伪造程序在 VM 上运行,VM 通过数据包嗅探监控局域网。每当它看到ICMP echo(回声)请求,无论目标IP地址是什么,我们的程序应立即发送echo(回声)回复,通过使用数据包伪造技术。因此,无论机器 X 是否存活(alive),ping程序总会收到回复,表示 X 是存活(alive)的。我们需要使用 Scapy 来完成此任务。
在实验中,我们将从用户容器中ping三个 IP 地址。
|----------------|-----------------------------------------------|
| ping 1.2.3.4 | 互联网上的不存在主机a non-existing host on the Internet |
| ping 10.9.0.99 | 局域网上的不存在主机a non-existing host on the LAN |
| ping 8.8.8.8 | 互联网上的存有的主机an existing host on the Internet |
我们可以看到,当我们ping 1.2.3.4时,显示的无法链接。
五、实验结果及分析
我们可以自行构造相关的容器以及虚拟的攻击主机,通过对数据包进行伪造,同时利用自行设计的容器即除却攻击者以外的主机进行嗅探,能够获取相关的数据包信息。但是针对我们主机上不存在的地址时,我们无法进行连接并获取相关的信息。
六、总结
通过本次实验我们对数据包的进行嗅探和伪造。并且利用了Wireshark,Tcpdump,Netwox,Scapy等工具辅助实验地进行。同时我们进一步了解这些工具是如何工作的,即在软件中如何实现数据包嗅探和伪造。