# 漏洞简介

在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 详解与复现的更多相关文章

  1. SENet详解及Keras复现代码

    转: SENet详解及Keras复现代码 论文地址:https://arxiv.org/pdf/1709.01507.pdf 代码地址:https://github.com/hujie-frank/S ...

  2. IntelliJ IDEA 2020.1.1 x64 Debug 断点调试模式详解

    前言 对于初入职场的萌新们来说,很多都还不会 Debug 断点模式.记得我刚写代码的时候,也是通过 System.out.println() 一行一行的把变量打印出来看.其实强大的编辑器已经帮我们做好 ...

  3. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  4. 2020了你还不会Java8新特性?(五)收集器比较器用法详解及源码剖析

    收集器用法详解与多级分组和分区 为什么在collectors类中定义一个静态内部类? static class CollectorImpl<T, A, R> implements Coll ...

  5. MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动

    MVC图片上传详解   MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...

  6. linux查看端口及端口详解

    今天现场查看了TCP端口的占用情况,如下图   红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...

  7. cron表达式详解

    @Scheduled(cron = "* * * * * *") cron表达式详解 1.cron表达式格式: {秒数} {分钟} {小时} {日期} {月份} {星期} {年份( ...

  8. VSFTPD全攻略(/etc/vsftpd/vsftpd.conf文件详解)

    /etc/vsftpd/vsftpd.conf文件详解,分好类,方便大家查找与学习 #################匿名权限控制############### anonymous_enable=YE ...

  9. CNN详解

    CNN详解 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7450413.html 前言 这篇博客主要就是卷积神经网络(CNN) ...

随机推荐

  1. Android Studio 之 用 Drawable resource file 美化 Button 样式

    shape •新建 Drawable resource file 点击 app/src/main/res 找到 drawable 文件夹,右击->New->Drawable Resourc ...

  2. 一文彻底搞定Hystrix!

    前言 Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用于 ...

  3. 翻译:《实用的Python编程》09_01_Packages

    目录| 上一节 (8.3 调试) | 下一节 (9.2 第三方包) 9.1 包 如果编写一个较大的程序,我们并不真的想在顶层将其组织为一个个独立文件的大型集合.本节对包(package)进行介绍. 模 ...

  4. Linux apt命令使用 以及 文本流和重定向

    apt (Advanced Packaging Tool) 是一个在Debian和Ubuntu中的Shell前端软件包管理器. apt命令执行需要超级管理员权限(root). apt语法 apt [o ...

  5. 8. vue给标签动态绑定title

    在利用vue开发时,如果标签宽度比较小,我们需要利用overflow:hidden;text-overflow:ellipsis;white-space: nowrap;对其进行隐藏,但隐藏后如何读其 ...

  6. 18. VUE created 方法作用

    一般可以在created函数中调用ajax获取页面初始化所需的数据. 实例的生命周期: 每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如,实例需要配置数据观测(data observer ...

  7. Day07_37_深度剖析集合中的contains()方法

    深度剖析集合中的 contains()方法 contains()方法查找集合中是否包含某个元素 contains() 底层使用的是 equals()方法 当contains()方法拿到一个对象的时候, ...

  8. 解决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这个表( ...

  9. 关于Redis客户端显示中文或中文乱码问题的解决

    关于Redis客户端不显示中文或者显示中文乱码,网上有些解决办法不全面的,都是漏了步骤不讲,简直瞎扯.在此记录一下解决方式. 刚开始使用Redis客户端的时候,本身就是默认不支持显示中文的. 例如,进 ...

  10. Redis 面试必备知识点

    1.Redis 简介 是一个用 C 语言开发的,高性能的键值对数据库. 数据存在于内存,读写速度快. 可用来做缓存.分布式锁.消息队列. 提供多种数据类型来支持不同的业务场景. 支持事务.持久化.Lu ...