频道栏目
首页 > 资讯 > 安全资讯 > 正文

iOS/OS X平台下syslogd的堆缓冲区溢出漏洞

16-01-22        来源:[db:作者]  
收藏   我要投稿



上周,苹果公司发布了iOS 9.2.1,此次更新是苹果公司在2016年对iOS设备的安全性能进行的首次更新。在此次更新中,苹果修复了syslogd(日志记录进程)中的代码执行漏洞(此漏洞是由Zimperium zLabs的安全研究专家Nikias Bassen和Joshua J.Drake发现的)。在这篇文章中,我们将会给大家描述这个漏洞的发现和验证过程,并且还会给大家介绍这个漏洞的详细技术细节。这个漏洞允许攻击者能够以root权限在iOS设备上执行任意的恶意代码,版本号在6.0至9.2之间的iOS设备都会受到这个漏洞的影响。

我们对iOS设备进行了漏洞检测,目的就是为了尽我们微薄的力量来提升iOS设备的安全性能。在我们的检测过程中,我们的漏洞检测工具曾引起过一次系统崩溃。尽管我们并没有对syslog的代码进行模糊测试,但是当我们对此次系统崩溃进行分析时却发现,我们的工具曾对syslogd的开源代码进行过全面的安全审查。我们对代码中的错误部分进行了分析和验证,并且能够通过这些错误代码来成功触发系统崩溃。在此之后,我们便将漏洞信息报告给了苹果公司安全团队的相关工作人员,苹果公司对此立刻进行了回应,并且修复了相应的安全问题。苹果公司在发布了iOS 9.2.1安全更新之后,Zimperium(该公司可以为客户提供企业化移动安全解决方案)的客户们不会再受到这个漏洞的影响。完整的安全公告如下:

iOS/OS X平台下syslogd的堆缓冲区溢出

受此漏洞影响的组件

/usr/sbin/syslogd

受此漏洞影响的系统平台和相应版本号:

l   iOS 6.0 至 9.2

l   OS X 10.9至10.11.2

供应商信息:

l   苹果公司

CVE信息:

l   CVE-2016-1722

syslog最新的开源代码版本:

syslog-267 (OS X 10.10.5)

http://opensource.apple.com/source/syslog/syslog-267/#sthash.qfQJ21ZE.dpuf

漏洞信息披露时间轴:

1.     安全研究人员于2015年10月26日发现并确认了这个漏洞;

2.     研究人员于2015年11月25日将漏洞信息报告给了苹果公司;

3.     苹果公司于2016年1月14日发布了iOS 9.2.1更新补丁,并修复了这个漏洞;

漏洞概述

系统在对内存进行重新分配的过程中,将有可能会出现的内存大小计算错误,这种错误将会引起syslogd的堆缓冲区溢出,尤其是当系统与多个客户端建立了连接时。

漏洞影响

本地权限提升,远程代码执行(针对在WiFi网络环境中的受信任设备),以及拒绝服务(DoS)。

漏洞描述

在iOS平台中,syslogd进程会以root权限运行。我们发现了一个堆溢出漏洞,该漏洞会导致系统的内存崩溃,在某些特定的情况下,这个漏洞还有可能允许攻击者在目标设备中执行任意代码。堆缓冲区中会发生数据越界,而这些数据则会被文件描述符的值所重写。如果攻击者的技术足够的好,那么在进行了特定操作之后,攻击者还可以控制重写的数据内容。无论怎样,这个漏洞的利用价值是非常高的。

背景信息

运行在苹果设备中的程序开发工具(通常是Mac OS X平台中的Xcode)通常会与syslog中继服务(com.apple.syslog_relay)进行连接。在与该服务进行连接之后,相应软件便能够访问系统中的日志文件(syslog)了,而且这种连接通常是通过USB连接线完成的。当攻击者与目标设备处于同一WiFi网络中时,攻击者就有可能与目标设备中的syslog服务进行远程连接。无论是通过哪种方式,在与相应服务进行连接之前,设备必须经过配置,而且必须信任远程主机。这也就是我们常说的“配对”,只有成功配对的设备才可以实现上述操作。

这个漏洞的利用过程涉及到主机和设备的感染。在我们进行了研究和分析之后,我们认为其他类型的攻击方式在实际中并不可行。由于受到密码保护的设备只有在成功解锁之后才能信任计算机。所以在利用这个漏洞之前,我们还需要相应设备的锁屏密码。运行在设备中的第三方应用程序是不可能与syslogd服务进行直接通信的。

详细信息

引起这个漏洞的根本原因就是add_lockdown_session函数(该函数存在于源文件syslogd.tproj/dbserver.c之中)中所存在的错误代码。在这个函数的执行过程中,程序会对内存空间进行重新分配,并且还会增加数组的长度。图片1显示的是部分漏洞代码。

 
图片1:我们从syslogd的源文件syslogd.tproj/dbserver.c中截取出了部分漏洞代码。其中红色部分的代码就是导致这个漏洞的根本原因。

第170行代码揭露了引起这个问题的根本原因。传递给reallocf函数的内存大小值是一个计算错误的值。这段代码原本应该利用sizeof(int)的值来增加数组(用于存储会话文件描述符的相关信息)的长度,但是由于运算优先级的规则导致了系统的计算错误。经过修改的正确代码如下:

global.lockdown_session_fds = reallocf(global.lockdown_session_fds,
(global.lockdown_session_count + 1) * sizeof(int));
原始代码只会在会话数量上加上sizeof(int)的值,但是我们在修改之后,会在会话数量上加1,然后再乘以sizeof(int)。在这种情况下,一个小括号就让一切变得不同了。

我们目前还无法获取到最新版本iOS和OS X中的源代码。如果我们需要证明最新版的苹果操作系统中仍然存在这些问题,那么我们还要对相应的二进制文件进行分析。除此之外,由于运算符优先级的规则,再加上这段代码已经是经过优化了的最简形式,一切都变得更加明显了。图片2显示的是我们对iOS 9.0.2中的syslogd二进制代码所进行的分析:


图片2:我们对iOS 9.0.2中的syslogd二进制代码进行了分析之后,发现了堆溢出的问题。

iOS 9.1中同样存在这个问题。我们甚至不用去检查其中的相关代码,只需要与com.apple.syslog_relay服务进行多次连接之后这个问题便出现了。我们也可以在OS X的syslogd代码中发现同样的问题。图片3显示的是我们对OS X 10.11.1中syslogd二进制代码的分析情况:


图片3: 我们对OS X 10.11.1中的syslogd二进制代码进行了分析之后,发现了堆溢出的问题。

请注意,上述示例中编译器都会将表达式“1*sizeof(int)”简化成“sizeof(int)”,这也使得这个漏洞变得更加的明显了。

当一个新的客户端与服务进行连接之后,会调用这个函数。该函数在首次执行时,会分配一个起始缓冲区,用以存储第一个文件描述符。请记住,sizeof(int)的值永远是4。而global.lockdown_session_count的值为0,所以第一次计算的大小值是正确的:即4字节。但是,当另一个客户端与其进行连接之后,global.lockdown_session_count的值为1,新的缓冲区大小将会被系统错误计算成5字节。在第三次连接之后,缓冲区大小又会变成6个字节,依此类推。

当程序将新建连接的文件描述符存储至global.lockdown_session_fds数组中时,堆溢出就发生了。我们可以从下图给出的代码中看到堆溢出发生的原因:


图片4:我们从syslogd的syslogd.tproj/dbserver.c源文件中提取到了上面这段代码。红色部分的代码就是引发堆崩溃的原因。

第179行代码会将长度为4字节的数据写入缓冲区,但内存空间不足,从而导致了内存溢出。具体信息可以从图片5中看到。


图片5:由于程序在重新分配内存空间时对内存大小的计算错误导致了堆溢出。将文件描述符写入内存时将有可能导致堆内存崩溃。

相关TAG标签
上一篇:如何安装Java 环境 JDK 最完整配置方法
下一篇: 50道Java线程面试题
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站