热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【技术分享】如何通过越界读取漏洞导出内存中的Yahoo!认证密钥

 

 https://img8.php1.cn/3cdc5/1600b/a6e/7f6aa8cc6050e48f.jpeg

翻译:興趣使然的小胃

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

一、前言

在我之前发布的关于Yahoobleed #1(YB1)的一篇文章中,我们了解到如何利用未初始化漏洞获取其他用户的私密图像信息。当时泄露的内存数据受制于JPEG图像的压缩机制,这种限制对某个图像大盗来说不成问题,然而如果我们想要窃取其他类型的内存内容,已泄露的这些数据仍稍显不足。

在这篇文章中,我会向大家介绍Yahoo!缩略图服务器上存在的另一个滴血(bleed)类的漏洞,我们可以将这个称之为Yahoobleed #2(YB2)。我们可以利用这个JPEG压缩缺陷(现在这个缺陷依然存在)提取原始的内存字节。结合“strings”工具的使用,我们还可以发现更多惊喜。

Yahoo!通过弃用ImageMagic的方式,在修复YB1漏洞的同时也修复了YB2漏洞。大家可以参考我之前的一篇文章,通过Yahoo!的回复进一步了解漏洞的修复细节。


二、可视化

http://p2.qhimg.com/t015878862d8a465176.png

当我们触发该漏洞时,Yahoo!服务器返回JPEG图片上会出现某些噪点。如上图所示,漏洞触发后,Yahoo!服务器返回了某张JPEG图片,将图片的某个64×4区域转化为PNG格式(即无损格式),放大后可以看到某些噪点,如上图所示。

这张图片有许多有趣的地方值得注意,就现在而言,我们可以观察到的是,图片的顶部存在几个指针图像。我曾在Project Zero上发表过有关指针可视化的一篇文章,如果你对这篇文章有所了解,你可以在各种内存泄露场景中发现这类指针的存在。至少对于x86_64架构的Linux来说,该系统中的指针通常都包含一个0x00007f的前缀。这类指针的包含几个特点,如:

1、使用相同的对齐方式重复类似的结构(64位系统上使用8字节对齐);

2、在指针块中,白色垂直条纹指向的是被对齐的最重要的字节,表示的是0x00(需要注意的是,由于输入文件的特殊格式,所泄露的字节实际上经过了取反处理);

3、在指针块中,紧挨其后的黑色垂直条纹所代表的含义是某行的7个比特的值被设置为0x7f。

4、在指针块中,紧挨其后的白色垂直细长条纹所代表的含义是该行的1个比特的值没有被设置为0x7f。

但我们还是会遇到JPEG压缩算法,这会不会对逐字节数据提取造成困难?我们会慢慢揭开这个谜题。


三、漏洞分析

我们不知道Yahoo!所使用的ImageMagic是否是最新版本,因此我们开始寻找相关的漏洞是否存在。我们已经知道Yahoo!支持RLE格式,之前我在一篇文章中介绍了如何使用某个技巧挖掘Box.com的内存损坏漏洞,也许我们可以使用相同的技巧对Yahoo!进行测试。

非常有趣的是,漏洞利用文件并不会导致任何文件崩溃,但服务器依然渲染了所有的测试文件,而最新版本的ImageMagic完全不会渲染这些文件。经过一番思考,我认为最有可能的解释就是,Yahoo!所用的ImageMagic的确是存在漏洞的老版本,但根据我们对YB1漏洞的分析,Yahoo!使用了不一样的堆设置,受对齐方式影响,我们的堆越界访问测试用例无法在Yahoo!上生效。

为了验证这个假设,我们构造了一个堆越界写RLE文件,足以覆盖堆中的某一小块数据(64字节大小,大约会有16个字节被覆盖),并将该文件上传到Yahoo!上。访问缩略图URL后,服务器会较为稳定地(以大约50%左右的概率)返回如下结果:

http://p5.qhimg.com/t0108a7d07edf2e33d9.png

这个结果看上去像是一个非常明显的后端错误,我们猜测它最有可能是一个SIGSEGV错误,这个错误与已有两年历史的RLE内存损坏问题有关。

但是我们今天的目标并不是如何利用这个RCE内存损坏错误,虽然这个过程肯定非常有趣。我们的目标是通过滴血攻击来提取数据。现在,我们手上拥有的是一个已有2.5岁年龄的ImageMagick,对于这个版本的ImageMagick而言,肯定有许多漏洞已经被修复了。经过一番搜索,我们找到了一个候选漏洞:一个已有2年以上历史的、已经在SUN解码器中修复的越界漏洞。在这个漏洞的修复代码中,开发者似乎对长度做了相关检查,同时更加彻底地应用长度检查过程,使其能够将色深(bit depth)为1的图像包含在内。让我们稍微研究一下没有打上补丁的代码,并且深入跟踪程序对色深为1的图片的解码路径,我们可以发现如下代码(位于coders/sun.c中):

sun_info.ImproperImageHeader");
bytes_per_line=sun_info.width*sun_info.depth;
sun_data=(unsigned char *) AcquireQuantumMemory((size_t) sun_info.length,
sizeof(*sun_data));
[...]
    count=(ssize_t) ReadBlob(image,sun_info.length,sun_data);
    if (count != (ssize_t) sun_info.length)
      ThrowReaderException(CorruptImageError,"UnableToReadImageData");
 
    sun_pixels=sun_data;
    bytes_per_line=0;
[...]
    p=sun_pixels;
    if (sun_info.depth == 1)
      for (y=0; y < (ssize_t) image->rows; y++)
      {
        q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
        if (q == (Quantum *) NULL)
          break;
        for (x=0; x < ((ssize_t) image->columns-7); x+=8)
        {
          for (bit=7; bit >= 0; bit--)
          {
            SetPixelIndex(image,(Quantum) ((*p) & (0x01 << bit) ? 0x00 : 0x01),
              q);
            q+=GetPixelChannels(image);
          }
          p++;
        }

因此,我们发现代码在处理色深为1的图像时存在一个非常明显的问题:

1、假设该图片的属性为:width(宽度)=256, height(高度)=256, depth(色深)=1, length(长度)=8;

2、色深为1的图像会导致与sun_info.length对比的number_pixels的检查过程被绕过;

3、sun_data所分配的缓冲区大小为8字节,而程序从输入文件中读取了这8个字节;

4、然后程序按每个像素1个比特的方式对图片进行解码。在这个过程中,sun_data总共需要(256*256)/8 == 8192个字节,但只有8个字节可用;

5、然后就出现大量的越界读取问题;程序实际上是在一片越界内存中对图片进行渲染。


四、漏洞利用

漏洞利用文件只有40个字节,因此我们可以在十六进制编辑器中观察这个图片的每个字节的含义:

http://p2.qhimg.com/t01fbad34c7e16ddb8d.png

59 A6 6A 95:                 头部

00 00 01 00 00 00 01 00:   图片大小256 x 256

00 00 00 01:                 图片色深:每像素1比特

00 00 00 08:                 图片数据长度为8

00 00 00 01:                 图片类型为1:标准图片

00 00 00 00 00 00 00 00:   map类型为空,长度为0

41 41 41 41 41 41 41 41:   8字节的图片数据

对于这个漏洞利用文件,我们可以操纵的最为有趣的一个变量就是图片数据长度(image data length)变量。只要我们将其大小控制在(256 * 256) / 8以内,我们就能复现越界读取漏洞。但越界读取从哪个位置开始呢?它会在图片数据分配缓冲区的末尾开始。通过改变图片数据的大小,我们最终有可能操纵堆中不同的相对地址(也许这些地址与缓冲区的开始或结束位置在距离上关系更为密切)。这样一来我们有可能能够读取某些有趣的数据。


五、信息提取

显然我们可以利用这个漏洞来提取信息,这也是这个漏洞真正有价值的地方所在。正如可视化部分所描述的内容,我们可以通过一个JPEG压缩文件来尝试提取信息。事实上我们可以通过ImageMagick获得一张JPEG灰度图像,因为前面每像素1比特的漏洞利用文件会生成一个黑白相间的图形。我们可以利用JPEG灰度图片较好地实现信息提取。人们之所以设计JPEG压缩算法,主要是想欺骗人眼对图片的直观感知。相对比真实的颜色而言,人类视觉对颜色的亮度更为敏感,因此在压缩算法中,颜色数据通常会比亮度数据丢失的信息更多(我们主要是通过YCbCr颜色空间实现这一点)。而JPEG灰度图像中只有亮度数据存在。

回头看看用于信息提取的那张JPEG图像,我们仍然会遇到JPEG压缩算法。我们会被这个困难所阻拦吗?答案是否定的。因为我们的漏洞利用图片是一张每像素1比特(黑色或白色)的图片,因此我们只需要在信息提取的JPEG文件中精确控制每个像素的1比特信息熵即可。虽然某些白色像素实际上是有点浅灰色而不是全白色,且某些黑色像素实际上是有点深灰色而不是全黑色,但每个像素仍然非常接近于黑色或者白色。我当然没有经过严密的数学计算,但事实上,对于Yahoo!服务器所使用的JPEG压缩算法而言,每个像素的确包含1比特的信息熵。根据我的统计,与白色偏差最大的那个像素颜色大约为85%的白色(即非常浅的灰色),而信息丢失的阈值当然更低,可以达到50%或者以下。

我们可以尝试从JPEG文件中恢复原始的字节,只需要使用如下的ImageMagick转换命令即可:

convert yahoo_file.jpg -threshold 50% -depth 1 -negate out.gray

对于本文开头的那个JPEG文件而言,恢复出来的原始内存字节如下所示:

0000000 d0 f0 75 9b 83 7f 00 00 50 33 76 9b 83 7f 00 00
0000020 31 00 00 00 00 00 00 00 2c 00 00 00 00 00 00 00

从中我们可以看到两个指针:0x00007f839b75f0d0以及0x00007f839b763350。


六、字符串及密钥

因此,现在我们有了一个在字节数据上相当可靠的信息提取方法,我们可以从Yahoo!缩略图服务器上发现哪些有趣的字符串吗?我们找到了许多信息量很大的字符串,我们用“redacted”替换了其中敏感的信息:

SSLCOOKIE: SSL=v=1&s=redacted&kv=0

Yahoo-App-Auth: v=1;a=yahoo.mobstor.client.mailtsusm2.prod;h=10.210.245.245;t=redacted;k=4;s=redacted

https://dl-mail.ymail.com/ws/download/mailboxes/@.id==redacted/messages/@.id==redacted/content/parts/@.id==2/raw?appid=getattachment&token=redacted&ymreqid=redacted

是的,结果看起来非常严重。

除了会话密钥等有趣的字符串之外,我们还能看到其他信息吗?是的,我们可以通过某些路径、错误信息以及版本字符串发现服务器的确在使用ImageMagick,而且版本非常老:

/usr/lib64/ImageMagick-6.8.9/modules-Q16/coders/sun.so
ImageMagick 6.8.9-6 Q16 x86_64 2014-07-25 http://www.imagemagick.org
unrecognized PerlMagick method

显然,这些字符串可以作为这个漏洞的佐证,同时我们还可以注意到字符串中涉及到PerlMagick。我对PerlMagick并不熟悉,可能PerlMagick是用来实现进程中的ImageMagick,这也是为什么我们的越界图像数据能够读取这么多有趣信息的原因所在。


七、总结

这个漏洞非常有趣,我们发现服务器上存在内存泄露漏洞,可以将每个经过JPEG压缩的像素的少量数据编码后返回给我们,因此我们能够较为稳定地重新构造原始的字节,还原服务器所泄露的内存数据。

在已启用的解码器中,不加限制地使用老版本的ImageMagick是一件非常危险的事情,通过弃用ImageMagick,Yahoo!应该已经修复了这些问题。


推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • HTML学习02 图像标签的使用和属性
    本文介绍了HTML中图像标签的使用和属性,包括定义图像、定义图像地图、使用源属性和替换文本属性。同时提供了相关实例和注意事项,帮助读者更好地理解和应用图像标签。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
author-avatar
沙鹰之眼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有