CVE-2020-1350 详解与复现
| # 漏洞简介 |
| 在Windows上,DNS服务器是域控制器,其管理员是Domain Admins组的一部分。默认情况下,Domain Admins组是已加入域的所有计算机上Administrators组的成员,包括域控制器[8]。如果利用得当,攻击者可以在易受攻击的系统上远程执行代码,并获得Domain Admin权限,从而有效地损害了整个公司的基础架构。 |
| DNS服务器-dns.exe负责在安装了DNS角色的Windows服务器上回答DNS查询。 |
| CVE-2020-1350是DNS.exe在处理畸形DNS Sig消息时,由于对数据包的字段校验不严格,导致了整型溢出。DNS SIG 消息中包含对DNS记录集合的数字签名,DNS记录集合就是一种名字相同,或者类型相同的DNS消息集合。 |
| 漏洞类型:整数溢出导致基于堆的缓冲区溢出 |
| # 攻击流程 |
![]() |
| 攻击者可以配置一个恶意的域名evildomain.com,该域名的DNS指向的DNS服务器作为本次攻击的目标。 |
| > 1. 当客户端查询evildomain.com的DNS记录; |
| > 2. 目标DNS服务器向根域名服务器查询evildomain.com的NS记录; |
| > 3. 根域名服务器告诉目标DNS,evildomain.com的权威DNS服务器是3.3.3.3,并该记录缓存起来; |
| > 4. 客户端向目标服务器查询evildomain.com的Sig记录; |
| > 5. 目标服务器将请求转发给权威DNS服务器; |
| > 6. 权威DNS服务器返回畸形Sig查询结果; |
| 目标DNS服务器处理SigQuery的畸形消息时,将此消息缓存到自己的记录中,触发漏洞。 |
| # 漏洞函数 |
| 简言之就是整数溢出后导致堆溢出,将该漏洞抽象为以下模型: |
| ```c |
void Examples(char*` `in){ unsigned short len_p1 = len(in.p1); unsigned short len_p2 = len(in.p2); unsigned short len_p = len_p1 +` `len_p2; char buf =` `(char )malloc(len_p); memcpy(buf, in.p1, len_p1); } |
| ``` |
问题就出在 len_p 的计算上,假设 len_p1 = 0xFFD0,len_p2 = 0x40,相加后高位数据被丢弃,那么 0xFFD0 + 0x40 = 0x10010 = 0x10,所以实际分配的内存是 0x10 而不是 0x10010,而之后往 0x10 的空间内拷贝 0xFFD0 长度的数据,自然造成了内存溢出。 |
而在dns.exe!SigWireRead函数里面也有类似的溢出漏洞,如图所示第11行: |
![]() |
| 漏洞成因如下:ushort类型,为无符号16位类型。RR_AllocateEx 分配的大小只有16个bit,大小为0~65535,所以只要构造size 大于65535,造成整数溢出,而系统就会分配一个比实际数据量小的堆块,进而造成堆溢出,将整数溢出转化成堆溢出漏洞。 |
| # 漏洞利用: |
| 因此,触发此漏洞所需的全部操作就是让受攻击的DNS服务器向我们查询SIG记录,并使用长签名(长度&>=64KB)对其作出SIG响应。但是,UDP上的DNS的大小限制为512字节(如果服务器支持EDNS0,则为4096字节)。在任何情况下,这都不足以触发漏洞。 |
CheckPoint 找到一种方法可以突破上述限制:UDP 响应时将 DNS 头部的 TC 标志置 1,表示被截断,之后客户端便会尝试用 TCP 协议和服务器建立连接,并通过 TCP 协议传递数据。由于消息的前两个字节表示其长度,因此TCP上的DNS中消息的最大大小表示为16位,因此限制为64KB。TCP 协议在 53 端口上可传输长度最大为 65535 的 DNS 数据,这无疑给该漏洞创造了先决条件。如下图:红框中的表示TC置位字段: |
![]() |
| 但是,即使是长度为65,535的消息也不足以触发漏洞,因为消息长度包括报头和原始查询。计算传递给RR_AllocateEx的大小时不考虑此开销。那么,该漏洞如何触发呢?继续往下看,首先了解一下域名编码和域名压缩。 |
| ## 域名编码 |
| eg:对于完整的一个域名www.baidu.com,需要14个字节: |
![]() |
| 可以看到第一个字节 是3,表示之后会有3个字节的字符。 |
| ## 域名压缩 |
域名压缩是 DNS 协议节省空间的一种方式,因为请求中的域名字符会频繁出现在响应包的内,故采用了一种标志+偏移的格式来压缩域名。压缩方式很简单:1 + 1 + offset,即最高 2bit 位为 1 时代表了将采用域名压缩,剩余的组合为偏移值(基地址为 DNS 头),如下图:响应区域中的 Name 字段为 0xc00c,明显是被压缩过的,最高 2bit 位是标志,剩余的 bit 位组合得到的值为 0xc,所以当前 Name 表示的字符串在 DNS 头部向后偏移 0xc 的位置,也就是图中红框中 0x3 开始(0x50 表示 DNS 头起始位置)的域名 bbs.pediy.com。 |
![]() |
因此,可以将域名压缩的偏移值指向一片可控的区域,而不是指向查询时域名,就完全有可能使得域名的长度大大增加,比如在这里修改为c0 0d,那么表示域名从0x62开始,说明后面有0x62个字节的字符,然后依次。这样就使得源代码第11行中的 sigName.Length 的大小变大。 |
| 注意:DNS name长度最大为0XFF |
| 所以,可以在不改变原来数据包大小的情况下,将sigLength+sigName.length+0x16 的大小,大于65535,造成整数溢出。分配一个小的空间缓存,然后导致堆溢出。 |
| # POC分析和漏洞复现 |
| 部分poc代码,大体就是构造sig响应消息。具体POC,在这里:https://github.com/maxpl0it/CVE-2020-1350-DoS |
![]() |
| ## 实验环境: |
| Windows Server 2008 R2 sp1 和 kali linux |
| ## 复现过程: |
| 1.在windows server 2008 安装dns服务器,并配置静态ip |
2.在kali 中运行脚本sudo python sigred_dos.py evil_domain_name |
| 3.在受害者服务器配置转发器,转发器ip为kali 机的ip。 |
| 4.在受害者服务器使用nslookup命令查询9.evil_domain_name: |
| ```shell |
| nslookup -type=sig 9.ibrokethe.net 127.0.0.1 |
| ``` |
| 5.查看kali,发现会发现收到了一个UDP连接,又收到了一个TCP连接。 |
| ## 复现结果: |
| 抓包结果如下: |
![]() |
| 由于本地无法解析“ibrokethe.net”,因此会以UDP协议向恶意服务器kali发送DNS查询,也就是kali收到的第一个UDP连接。恶意服务器查到了该域名,就向受害者发送响应包,设置TC位,通知受害者采用TCP重发原来的查询请求,并允许返回的响应报文超过512个字节。这是第二个DNS包。然后进行三次握手,受害者再次以TCP协议发送请求,这就是kali收到的TCP连接。之后,恶意服务器就可以利用TCP传输大于64KB的响应包发给受害者,触发漏洞,造成堆溢出。 |
| 然后,就可以进行远程代码执行等操作了。 |
| 可以看到在复现的过程,产生堆溢出,dns.exe进程发生崩溃,从而产生DOS攻击。如下图: |
![]() |
| # 漏洞修复 |
临时修复方案,修改注册表,限制tcp包的长度,TcpReceivePacketSize的值为0xFF00 |
| ```shell |
| HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters |
| DWORD = TcpReceivePacketSize |
| Value = 0xFF00 |
| ``` |
| 注意:必须重新启动 DNS 服务才能生效。 |
| # 总结: |
| 协议方面多多少少都会有我们所疏忽的问题,对于dns.exe开发者,最开始并未考虑到最大可以超过65535,造成溢出,代码并没有问题,造成该漏洞的关键点,主要是因为域名压缩。往往很多个疏忽点,凑到了一起就成了攻击者利用的漏洞。 |
| # 参考链接: |
| CVE-2020-1350 Windows Server DNS漏洞复现 |
| 漏洞利用剖析:带有CVE-2020-1350 SIGRed的RCE |
| CVE-2020-1350: Windows DNS Server蠕虫级远程代码执行漏洞分析 |
CVE-2020-1350 详解与复现的更多相关文章
- SENet详解及Keras复现代码
转: SENet详解及Keras复现代码 论文地址:https://arxiv.org/pdf/1709.01507.pdf 代码地址:https://github.com/hujie-frank/S ...
- IntelliJ IDEA 2020.1.1 x64 Debug 断点调试模式详解
前言 对于初入职场的萌新们来说,很多都还不会 Debug 断点模式.记得我刚写代码的时候,也是通过 System.out.println() 一行一行的把变量打印出来看.其实强大的编辑器已经帮我们做好 ...
- 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)
方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...
- 2020了你还不会Java8新特性?(五)收集器比较器用法详解及源码剖析
收集器用法详解与多级分组和分区 为什么在collectors类中定义一个静态内部类? static class CollectorImpl<T, A, R> implements Coll ...
- MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动
MVC图片上传详解 MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...
- linux查看端口及端口详解
今天现场查看了TCP端口的占用情况,如下图 红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...
- cron表达式详解
@Scheduled(cron = "* * * * * *") cron表达式详解 1.cron表达式格式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份( ...
- VSFTPD全攻略(/etc/vsftpd/vsftpd.conf文件详解)
/etc/vsftpd/vsftpd.conf文件详解,分好类,方便大家查找与学习 #################匿名权限控制############### anonymous_enable=YE ...
- CNN详解
CNN详解 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7450413.html 前言 这篇博客主要就是卷积神经网络(CNN) ...
随机推荐
- Android Studio 之 用 Drawable resource file 美化 Button 样式
shape •新建 Drawable resource file 点击 app/src/main/res 找到 drawable 文件夹,右击->New->Drawable Resourc ...
- 一文彻底搞定Hystrix!
前言 Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用于 ...
- 翻译:《实用的Python编程》09_01_Packages
目录| 上一节 (8.3 调试) | 下一节 (9.2 第三方包) 9.1 包 如果编写一个较大的程序,我们并不真的想在顶层将其组织为一个个独立文件的大型集合.本节对包(package)进行介绍. 模 ...
- Linux apt命令使用 以及 文本流和重定向
apt (Advanced Packaging Tool) 是一个在Debian和Ubuntu中的Shell前端软件包管理器. apt命令执行需要超级管理员权限(root). apt语法 apt [o ...
- 8. vue给标签动态绑定title
在利用vue开发时,如果标签宽度比较小,我们需要利用overflow:hidden;text-overflow:ellipsis;white-space: nowrap;对其进行隐藏,但隐藏后如何读其 ...
- 18. VUE created 方法作用
一般可以在created函数中调用ajax获取页面初始化所需的数据. 实例的生命周期: 每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如,实例需要配置数据观测(data observer ...
- Day07_37_深度剖析集合中的contains()方法
深度剖析集合中的 contains()方法 contains()方法查找集合中是否包含某个元素 contains() 底层使用的是 equals()方法 当contains()方法拿到一个对象的时候, ...
- 解决mysql You can't specify target table for update in FROM clause错误
mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表( ...
- 关于Redis客户端显示中文或中文乱码问题的解决
关于Redis客户端不显示中文或者显示中文乱码,网上有些解决办法不全面的,都是漏了步骤不讲,简直瞎扯.在此记录一下解决方式. 刚开始使用Redis客户端的时候,本身就是默认不支持显示中文的. 例如,进 ...
- Redis 面试必备知识点
1.Redis 简介 是一个用 C 语言开发的,高性能的键值对数据库. 数据存在于内存,读写速度快. 可用来做缓存.分布式锁.消息队列. 提供多种数据类型来支持不同的业务场景. 支持事务.持久化.Lu ...







