11

挖洞经验 | 用空字节(Null Byte)触发内存泄露的4万美金漏洞

 4 years ago
source link: https://www.freebuf.com/vuls/224088.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作为前言,当我在7月底发现本文中的漏洞时,我还不知道有“空字节溢出”这种类型的安全问题。我仅只是对一个标准Web应用的用户输入点进行了Fuzzing测试,就发现了这么一个有意思的漏洞,并获得了厂商高达$40,000美金的奖励。

直到近期,HackerOne上一个名为 “maxarr” 的用户 上报了一个关于Mail.ru存在内存内容泄露的漏洞 ,我感觉他的这个漏洞和我的非常相似,Mail.ru安全总监Sergey Belov也对该漏洞有了以下的说明:(Lua绑定到不安全的C语言函数时导致的内存信息泄露)

BNnyiuM.jpg!web “maxarr” 未在漏洞报告中给出具体细节,但Sergey Belov推特内容中透露出来的东西,让我对此前7月份发现的那个“空字节溢出”漏洞有了更准确的认识。在此我来做个分享。

漏洞发现背景

漏洞发现于DEF CON会议的前几天,当时我在旧金山闲了几天,并准备和一众朋友们开车到拉斯维加斯参加DEF CON大会,凑巧就是在这放松的几天当中,我发现了该漏洞。

朋友们准备驾车前往拉斯维加斯,其实本来我是不想去参加DEF CON大会的,但在最后时刻我甚至连行李和衣服都没准备,就决定加入了他们的公路之旅。我随便买了一些换洗的衣服,并与大家相约第二天早上在附近的星巴克做一波测试,之后就上路前往DEF CON。

意外地发现

当我一开始测试目标Web应用时,我就想到了用一些字符串技巧去注册测试账户,比如用“victim”加上一些空字节、CRLF控制符、空格或其它Unicode等特殊字符当做注册的用户名,这样做的想法在于,有些后端Web应用在处理这些特殊字符时,会把这些特殊字符简单的删除,由此做为攻击者来说,就能获得与目标账户“victim”同等的账户权限了。

我想如果这种思路最终可行,那么整个测试逻辑应该是这样的:攻击者用victim%00作为注册用户,有些独特的victim%00到达前端注册程序后,经处理操作,并被转向后端服务进行处理。关键点就在于,当victim%00经过前端和后端的两次处理后,其中的空字节%00在到达后端服务时就被删除了,所以最终变成了victim。

zqmueqV.jpg!web

尽管想的美好,但最终测试证明这种思路无效不可行,把它分享于此的目的在于,让大家知道我是如何来分析这个目标应用的。接下来,我有点不服气,还想用类似方法再测试其注册机制。这一次,我把测试点放到了用户的注册绑定邮箱上,想看看后端服务会不会把空字节%00做删除处理。我构造的注册绑定邮箱如下:

 victim%[email protected] 

在包含上述邮箱的请求发出之后,响应成功后,它变成了以下的样子:

 [email protected] 

也就是说,目标服务端把蹊跷地把空字节“%00” 替换成了 “L”,当时我就就得非常奇怪,然后又在注册绑定邮箱当中多添加了两个“%00” ,如下:

 victim%00%00%[email protected] 

这一次,服务端响应回来的消息中,注册绑定邮箱变成了

 [email protected] 

起初看上去像是一些随机数据被空字节置换出来的感觉,后来经我发送了更多的%00测试发现,除了在POST请求体中有最大字符限制之外,服务端对%00根本没做任何限制,因此,我又在POST请求中发送了更多大量的%00空字节,最终,差不多等了快10多秒,服务端响应回来了一些让我诧异的东西。

这些响应消息中包含了很多可读的内存数据内容,于是,我又重要发了一次POST请求,之后响应回来的消息内容又变成了另外相似的可读内存数据。

在星巴克中,当我把这些东西展示给朋友们看时,他们都非常吃惊。每一次的请求重放,响应回来的可读内存信息都是不一样的,其中包含了RSA私钥信息、内部HTTP请求、用户相关的DOM、明文的用户名密码,以及非常之多的敏感信息……。最后,我们返回了酒店,我也及时地整理了漏洞信息并进行了上报。

漏洞原因

刚开始,我们大家都只是胡乱猜测,并认为该漏洞是某种内存破坏或溢出漏洞,因为我们在请求中使用了多个空字节。但看了Sergey Belov的推特发贴后,我才恍然大悟,漏洞原因在于,Web前端与后端在处理数据时的差异,当用户输入的注册名传递给了后端底层C语言应用的某个不安全方法函数时,触发了内存信息泄露。

一开始,C语言应用希望从前端的注册应用中获取以下两个用户输入属性:

字符串

字符串长度

如果把 “abc%00” 当成注册用户名,前端应用在注册操作发生时会有以下处理:

字符串: abc%00

字符串长度: 4

如果完全由前端来执行处理,这是没有问题的,但是这个注册用户名在前端传递给后端底层C应用的过程中,里面的空字节被删除了,最终发送的消息如下:

字符串: abc

字符串长度: 4

如果对C语言有了解的话,大家应该知道,空字节(Null Byte)只是增加了字符串的长度,但并不真正占用字符串的值,空字节在程序中也被称为结束符,代表一个字符串显示的结束返回。为此,有了以上的数据转化差异,在字符串值返回到前端应用之前,由于服务端只需将字节数读入字符串值,因此,攻击者就可以构造一个非常大的空字符串区间去填满服务端内存区域,去间接地用空字节强迫后端内存向前端返回显示某些信息,因此触发了内存泄露。大概流程如下:

fURjiuM.jpg!web

攻击者只需简单地反复提交这个请求,就可在前端获得多达M字节的内存信息量,如下:

AjM7fa7.jpg!web

上图是一个发送请求并获得内存响应信息的过程,由于内存的动态数据非常之大,所以我们的证明过程就是想办法提取大量的数据内容,并从中发现系统的敏感信息。请注意,因为我们的测试是经过授权的,所以不建议大家未授权开展这样的测试。

最后,我们编写了一个自动测试、收集并查找敏感内存信息的脚本,简单直接地显示出了漏洞的PoC利用和实际危害,然后匆匆上报给了厂商。这是一个非常不可思议的漏洞,抱歉我不能透露更多漏洞细节,但众测平台和厂商安全团队的快速反应让我深受感动。

漏洞上报和处理进程

 2019.7.30  01:30    漏洞上报 
 2019.7.30  02:47   厂商反馈 
 2019.8.19   00:24   赏金发放 
 2019.8.11   19:05    漏洞修复 

*参考来源: samcurry ,clouds 编译整理,转载请注明来自 FreeBuf.COM


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK