SEED:Sniff and Spoof
课程实践报告
课程 网络攻防技术(314006040)
课 序 号 3
作业名称 网络流量嗅探和窃取实验
评分
姓名 杨森 学号 2021141530084
评阅意见
一、 作业题目
嗅探和欺骗
二、 实验步骤及结果
1. 实验环境设置
1) 拓扑结构
网路接口bridge,host,none都是docker自己创建的。三个容器使用我们自定义的网络接口:636082fa98c9,这个网络接口相当于三个容器的交换机:
- 容器使用
首先进入Labsetup文件夹,使用命令dcbuild和dcup编译和启动容器。如果需要关闭:dcdown。
你可以通过以下命令(dockps)查看容器id:
如果需要使用某个容器的终端,需要执行命令:docksh
- 关于攻击机
共享文件夹/volumes:虚拟机和attacker容器之间的共享文件夹,为了方便在docker容器中使用虚拟机的编辑器编写的代码。
主机模式:对于桥接模式下的三个容器,他们并不能互相访问各自的网络接口,因为他们被桥接模式虚拟成局域网下的不同主机。将容器attacker修改为主机模式,那么他将可以访问虚拟机的所有网卡。
补充:
对于使用主机模式的容器,docker不会为其虚拟网络接口,而是直接使用宿主机的网络接口。我这里做了一个简单的实验,进入容器attacker对1.2.3.4发起ping:
这里并没有看到容器接口veth流量进行波动,说明docker并没有为主机模式的容器虚拟出网卡。
另外,使用虚拟机对容器attacker发起ping:
这里回环网卡波动,这就说明容器attacker是主机模式,并且使用虚拟机网卡。
第一部分:使用scapy嗅探和欺骗
2. 嗅探数据包
使用scapy嗅探数据包是一件简单的事情,这里将网卡设置为三个容器的桥接网络:
- 使用root权限对sniff的影响
使用root权限:
sniff函数对于每一个捕获的数据包都会调用回调函数print_pkt打印出数据包相关信息:
打开一个终端使用命令:ping 10.9.0.5,这里我使用-i参数将时间间隔设置为一秒:
另一个终端以root权限运行python程序进行监听:
上面有两个数据包,第一个ICMP报文类型为“request”,源IP为10.9.0.1,目的IP为10.9.0.5;第二个ICMP报文类型为“reply”,源IP为10.9.0.5,目的IP为10.9.0.1。结合在ping命令终端看到的情景,这里sniff程序嗅探数据包成功。
不使用root权限运行:
python程序中打印“sniff…”语句成功执行,执行sniff函数权限不够导致报错。这是因为sniff函数会首先默认以混杂模式打开一个网络接口,因此需要root权限。
2) 采用不同的过滤方式嗅探数据包
只捕获ICMP协议报文:
在上面“使用root权限对sniff的影响”中已经完成此实验,上面的代码就是过滤的icmp协议:
Icmp报文:
捕获指定IP的23端口的TCP报文:
在Linux和Windows操作系统下,23端口都用于远程连接服务Telnet。可以使用telnet命令发送连接的TCP数据包。
Sniff程序成功嗅探到telnet的数据包:
捕获发往特定子网的数据包:
ping一下这个子网就行,如果捕获到数据包证明程序正常:
- 伪造ICMP数据包
修改源IP为hostA(10.9.0.5),向hostB(10.9.0.6)发送ICMP请求报文:
运行spoof程序,监听桥接网络,发现伪造的ICMP请求报文和接收到ICMP回应报文:
在伪造源IP的ICMP报文中可以看到,attacker的mac地址如下。
然而ICMP回应报文的mac地址却是hostA的:
这说明更改ICMP报文的源IP地址,会让对方相信这个错误的IP地址。
4. Traceroute程序
Tracert依靠于ICMP协议,通过将ttl从1不断加大到能达到目的IP从而了解数据包的网络经过:
运行程序:
Warshark查看详细信息:
- 嗅探然后欺骗
如果嗅探到ping包,则伪造ip返回一个ping响应包,那么只需要在回调函数中伪造源IP的ping回应包即可,这里将嗅探到返回的数据包附加上负载“spoof”便于区分:
Ping 1.2.3.4,一个不存在于网络的主机:
进入容器attacker对1.2.3.4发起ping,运行编写的程序:
Warshark抓包,在ICMP回应报文出现负载“spoof”,程序成功发送欺骗的数据包:
Ping 10.9.0.99,一个不存在的局域网主机:
进入容器attacker对10.9.0.99发起ping,运行编写的程序:
打开warshark,发现编写的程序成功并没有成功返回欺骗报文,因为在arp解析失败以后icmp包根本就没有发出,而是系统认为目标不可达:
Ping 8.8.8.8,一个存在于网络的主机:
进入容器attacker对8.8.8.8发起ping,运行编写的程序:
在容器attacker中ping8.8.8.8实际上就是虚拟机对8.8.8.8进行ping,因此warshark中桥接网络并没有attcker发的包。由于操作系统将伪造的响应包算作回环网络里面,因此回环网络有流量波动,打开any网络接口(包括回环)查看伪造的响应包,发现负载“spoof”的响应包:
在hostA(10.9.0.5)运行程序对8.8.8.8发起的ping,运行编写的程序:
在warshark中查看,可以发现同一个ICMP请求收到了两个回复,带有负载“spoof”的回复是程序sniff_spoof.py响应的:
另外当hostA对8.8.8.8进行ping,发现宿主机也在ping?
第二部分:编写嗅探和伪造数据包的程序
6. 编写数据包嗅探程序
在这个任务中,需要在虚拟机与容器attacker的共享文件夹volumes中编辑C代码。docker-cp a.out <容器id>:/tmp
1) 了解一个嗅探器如何工作
嗅探器实际是通过网络接口
对于链路层帧结构:同步码(8字节),目的MAC地址(6字节),源MAC地址(6字节),类型(2字节),数据部分,CRC校验码(4字节)。当以太网帧中的类型字段的值为0x0800时,表示数据部分采用的是IPv4协议;当类型字段的值为0x86DD时,表示数据部分采用的是IPv6协议。
对于网络层包结构:
根据提供的代码编写一个能够打印捕获数据包的源/目的IP地址的程序:
问题一:描述库调用的顺序。
首先调用pcap_open_live函数打开网络接口;然后使用pcap_compile函数编译BPF过滤表达式;最后使用pcap_loop函数循环捕获数据包并调用回调函数,pcap_close进行关闭网卡。
问题二:为什么需要root权限运行嗅探器程序,是哪个地方需要root权限。
在程序中调用pcap_open_live函数来打开网络接口进行数据包捕获时,需要root权限。在调用pcap_compile和pcap_setfilter函数来编译和设置数据包过滤规则时,同样需要root权限。
问题三:演示打开和关闭混杂模式的区别。
开启混杂模式,使用hostA对hostB发起ping:
在attacker中运行sniff程序,可以发现即使源/目标地址并不是自己,但是仍然捕获了这些数据包:
关闭混杂模式,同样使用hostA对hostB发起ping,程序已经不能捕获hostA和hostB之间的通信:
由此可知,混杂模式可以捕获经过网卡的其他数据包。
- 编写过滤器
捕获两个特定主机的ICMP数据包:
根据BPF过滤规则编写即可。
在hostA中对hostB发起ping,执行编写的程序:
可以看到嗅探到了icmp数据包,并且打印出了源/目标IP:
捕获端口10-100的TCP数据包:
使用telnet服务对hostB发起请求,并执行编写的程序:
可以看到成功捕获到指定的数据包:
然而使用nc工具对attacker发起请求,执行编写的程序进行嗅探:
可以看到没有捕获到任何内容,但是nc工具却捕获到了101端口tcp数据包:
- 嗅探密码
由于telnet服务使用明文传输数据包,因此使用嗅探器可以窃取telnet协议发送的数据包当中的密码。
这里根据tcp协议字段判断telnet报文,然后根据找出telnet数据的指针位置,计算数据长度,最后打印出数据部分:
运行程序,成功捕获到telnet数据部分,可以看到“pas…”部分就是我输入的密码字段:
- 欺骗
对于一般用户,操作系统限制对TCP/IP一些字段的控制。但是,如果拥有root权限,就可以控制TCP/IP的所有字段。
原始套接字提供了程序员对数据包的绝对控制,使用原始套接字非常简单;它包括四个步骤:(1)创建一个原始套接字,(2)设置套接字选项,(3)构造数据包,(4)通过原始套接字发送数据包。
1) 编写一个欺骗程序
伪造数据包,需要创建原始套接字,它允许对数据包有足够的控制。其次,需要定义网络层,运输层的结构体,方便构造数据包,这里引用netinet库实现这个功能:
可以看到warshark成功捕获到伪造的数据包,这说明欺骗程序生效:
- 伪造ICMP请求数据包
相比上面的程序,这里需要构造icmp协议的结构体:
运行编写的程序:
在warshark中成功捕获到程序发送的数据包:
问题四:可以将IP数据包长度字段设置为任意值,而不管实际数据包有多大吗?
在构造IP数据包时,IP数据包长度字段是指整个IP数据包的长度,包括IP头部和数据部分。这个字段的取值应当是整个IP数据包的实际长度,而不是任意值。
如果发送的数据包长度超过了MTU(最大传输单元),那么数据包将被分片成多个较小的数据包。在这种情况下,每个分片的IP数据包长度字段会被设置为对应分片的长度,而不是整个数据包的长度。
问题五:使用原始套接字编程,是否必须计算IP标头的校验和?
在使用原始套接字(raw socket)发送自定义的IP数据包时,如果设置了IP_HDRINCL选项,就不需要手动计算IP头部的校验和。当IP_HDRINCL选项被启用时,内核会自动计算IP头部的校验和,并填充正确的数值。
否则,需要使用程序计算校验和,确保目标主机不会舍弃这个数据报。
问题六:为什么需要root权限才能运行使用原始套接字的程序?如果在没有root权限的情况下执行程序,程序会在哪里失败?
使用原始套接字可以直接访问链路层和网络层,发送自定义的数据包,这可能会对网络造成安全风险,因此需要特权才能执行。
如果在没有root权限的情况下执行使用原始套接字的程序,程序在以下步骤会失败:调用socket函数时会返回错误,因为创建原始套接字需要特权。如果尝试设置IP_HDRINCL选项也会失败,因为设置该选项同样需要特权。
因此,如果没有root权限,程序将无法成功创建原始套接字或者设置IP_HDRINCL选项,从而无法发送自定义的IP数据包。
8. 嗅探,发送欺骗数据报
将上面编写的嗅探程序做修改,过滤icmp请求报文;修改回调函数,通过传入的数据包获取源/目标IP地址,修改伪造程序为构造icmp响应报文,并修改填入的源/目标ip即可:
对1.2.3.4发起ping,运行程序:
在warshark中可以看到捕获到程序发送的响应报文: