导航菜单
译文声明

本文是翻译文章,文章原作者synacktiv,文章来源:synacktiv.com原文地址:https://www.synacktiv.com/posts/exploit/memory-leak-and-use-after-free-in-squid.html

译文仅供参考,具体内容表达以及含义原文为准

Squid中的内存泄漏和UAF漏洞详解

 

几个月前,Synacktiv团队对开源项目Squid进行了安全评估。这篇博客文章描述了在审核期间发现的一些漏洞细节。

 

CVE-2019-18679:摘要认证中的信息泄露

当配置为使用摘要式身份验证方案时,Squid会使用407 Proxy Authentication Required状态代码响应不包含Proxy-Authorization标头的请求。

Squid中的内存泄漏和UAF漏洞详解

在响应中包含一个Proxy-Authenticate-HTTP头,向客户端提供对其进行身份验证所需的信息。即使不看源代码,我们也能注意到生成的随机数有些奇怪。如果我们对它进行base64解码并将其打印为QWORDS,则会得到可疑的东西,这看起来像一个内存地址:

Squid中的内存泄漏和UAF漏洞详解

让我们更仔细地看一下Squid中的摘要实现。此nonce由auth/Config.cc中定义的authenticatedigestnoncew函数生成。

Squid中的内存泄漏和UAF漏洞详解

在(1)处,我们可以注意到newnonce->noncedata.self包含newnonce对象的地址。

在生成之后,这个随机数对象由authenticatedigestnoncenoncenb64函数编码,然后包含在代理授权HTTP响应头中。

Squid中的内存泄漏和UAF漏洞详解

该authenticateDigestNonceNonceb64()函数仅返回对象的键值。该nonce->key字符串在authDigestNonceEncode中进行初始化,且authDigestNonceEncode只对非数据结构执行base64编码,而不进行任何形式的哈希运算:

Squid中的内存泄漏和UAF漏洞详解

由于_digest_nonce_data包含指向digest_nonce_h对象的指针,因此我们可以在Proxy-Authorization HTTP头部中获取它。

Squid中的内存泄漏和UAF漏洞详解

我们可以通过构造恰当的信息复杂度,在Squid的日志中进行检查。

Squid中的内存泄漏和UAF漏洞详解

Squid中的内存泄漏和UAF漏洞详解

这给了我们一个很好的机会来绕过ASLR。

在我们之前,另一位研究人员报告了此漏洞,并在2019年11月发布的Squid 4.9中修复该漏洞。

但是,修复方式有些奇怪,他们没有从__digest_nonce_data中删除digest_nonce_h指针,而是决定使用MD5对结构体进行哈希处理并将结果返回给用户。

Squid中的内存泄漏和UAF漏洞详解

但是,如果攻击者想确定用于计算MD5摘要的每个组件的值,则有可能对MD5摘要执行脱机暴力攻击检索digest_nonce_h指针。让我们回顾一下这些组件。

creationtime是__digest_nonce_data中的第一个字段,它是用户已知的摘要对象创建的时间戳(以秒为单位)。

另一个要确定的字段是randomdata,由Mersenne Twister PRNG生成的uint32_t值。

Squid中的内存泄漏和UAF漏洞详解

当用当前时间戳(以秒为单位)生成第一个nonce时,是以PRNG作为种子的。因此,要确定randomdata,攻击者将需要知道:• Squid自启动以来处理的第一个请求的时间戳,• Squid自启动以来生成的随机数。但是,可以通过利用一个漏洞使Squid服务器崩溃,就可以确定这两个值,因为PRNG是在crash后的第一个请求当做种子植入的。

这将导致攻击者对MD5摘要进行暴力攻击以检索digest_nonce_h指针,从而绕过ASLR。

在x86_64Linux上,用户地址空间是从0到1<<47(0x80000000000)。由于digest_nonce_h对象的分配总是与0x10字节对齐,因此bruteforce的整个密钥空间大小是47-4=43位。考虑到现代密码破解机每秒可以计算2720亿MD5哈希,一次完整的暴力攻击大约需要30秒。

在Squid 4.10中对该漏洞进行了静默修补,把digest_nonce_h指针从结构体中删除。

 

CVE-2020-11945:摘要验证中的UAF

所述的digest_nonce_h结构定义auth/digest/Config.h。

Squid中的内存泄漏和UAF漏洞详解

由于客户端可能并行发送多个请求,nonce对象包含一个引用计数器。如今,使用有符号的16位整数存储引用计数器似乎相当危险,因为它可能会溢出,触发UAF漏洞。

让我们看看这里的情况是否如此。

通过查看代码,我们了解到该引用计数器的定义如下:

创建nonce对象时实例化为1,

当Squid接收到使用nonce的新请求时,它将增加1,

当请求完成时,即当基础的UserRequest对象被销毁时,它将递减1,

当nonce被视为过期时,它将递减1,这意味着:

o 随机数到期日期已到,

o 随机数被用来发送更多的请求,该请求超过了授权阈值(在nonce_max_count配置设置中设置),

o 随机数的使用方式存在问题,例如,随请求发送的随机数与前一个计数不匹配。

当计数器为0时,nonce对象被释放

因此,如果我们在serRequest对象进行垃圾回收之前执行了足够的请求使计数器溢出,则我们应该能够触发一个Use-After-Free漏洞。

触发漏洞

首先,我们通过向Squid发送以下HTTP请求来生成新的随机数:

Squid中的内存泄漏和UAF漏洞详解

在Squid的日志中,我们可以观察到随机数的创建(具有正确的信息复杂度):

Squid中的内存泄漏和UAF漏洞详解

然后,我们建立了大量的TCP会话。一旦所有这些都达到建立的状态,我们便开始构造HTTP请求:

• 他们的nonce是之前创建的

• 它们的参数“response”是十六进制中任意选择的128位字(用于身份验证失败)。

Squid中的内存泄漏和UAF漏洞详解

思路是是输入引用计数器增加但身份验证失败的代码片段,从而防止对象的“nonce count”增加。因此,使用此代码片段可以任意增加引用计数器触发整数溢出。

Squid中的内存泄漏和UAF漏洞详解

由于负责递减引用计数器authDigestNonceUnink的函数在值为负时不执行操作,因此我们只需要并行发送32768个请求。

Squid中的内存泄漏和UAF漏洞详解

然后,我们可以使用单个请求将计数器一直增加到-1。

Squid中的内存泄漏和UAF漏洞详解

此时我们有一个nonce对象,其引用计数器为-1。为了实现UAF,我们需要两种请求:

• 一个可以控制生命周期nonce的请求A,

• 请求B,它将引用计数器增加到1,然后在完成后释放对象。

对于请求A,我们可以使用nonce成功地执行对受控制服务器请求的身份验证。然后,在服务器端,我们可以任意延迟响应,这将有效地防止Squid破坏关联的UserRequest对象。

对于请求B,不能使用用于增加引用计数器的相同类型的请求。实际上,当一个nonce对象在从缓存中删除之前就被删除(这基本上是有效nonce的列表),Squid会崩溃,并出现一个失败的断言。

Squid中的内存泄漏和UAF漏洞详解

因此,我们需要authDigestNoncePurge在释放随机数对象之前调用该函数。

Squid中的内存泄漏和UAF漏洞详解

通过跟踪调用authDigestNoncePurge的代码路径,我们可以找到两种从缓存中删除nonce的方法:

• 等待随机数到期,

• 通过使用无效的nonce计数(例如0)来使nonce无效。

第二个当然更方便,所以这就是我们要用的。

现在我们只需要:

执行2个请求A,将引用计数器递增为1

Squid中的内存泄漏和UAF漏洞详解

• 执行1个请求B,将计数器增加到2,然后将其从缓存中删除后,将其减少到1。

Squid中的内存泄漏和UAF漏洞详解

• 关闭请求A,将计数器减为0,从而释放随机数对象,

Squid中的内存泄漏和UAF漏洞详解

遗憾的是,事情的发展并非如我们预期的那样。我们释放了nonce对象,但并没有执行 free函数。实际上,在Squid中的Digest实现中,digest_nonce_h对象被分配到名为MemPoolMalloc的分配池中。

要正确释放nonce分配,需要触发池中分配回收机制。在Squid的默认配置中,这可以通过分配和释放至少300个nonce对象(通过用任意nonce发送B请求)来完成。

Squid中的内存泄漏和UAF漏洞详解

此时,存在一个UserRequest对象,该对象具有指向之前digest_nonce_h的悬挂指针。当最后一个UserRequest被销毁时,将使用该悬挂指针调用authDigestNonceUnlink函数。

如果我们关闭最后一个请求,而不事先执行任何喷射操作,则很可能在自由执行期间中止程序。

Squid中的内存泄漏和UAF漏洞详解

总而言之,我们在启用了摘要身份验证模块的Squid4.8默上成功触发了UAF。但是,在发送有效身份验证之前,很难确保nonce计数的值为-1,因此不太可能在野外利用此漏洞。

 

本文翻译自 synacktiv.com, 原文链接 。如若转载请注明出处。

相关推荐

CVE-2020-0904:Hyper-V类型混淆任意地址解引用漏洞分析

译文声明 本文是翻译文章,文章原作者Daniel Fernandez Kuehr,文章来源:labs.bluefrostseC++urity.de 原文地址:https://labs.bluefrostsecurity.de/advisories/bfs-sa-2020-003/ 译文仅供参考,具体内容表达以...

JustSystems Ichitaro(一太郎)缓冲区溢出漏洞

  漏洞简介 IC++hitaro(一太郎)是日本JustSystems公司的一套文字处理软件。 JustSystems Ichitaro在处理JTD文档的过程中存在基于堆的缓冲区溢出漏洞,允许远程攻击者可利用该漏洞构建恶意文件,诱使用户解...