找回密码
 开放注册

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

搜索
查看: 743|回复: 0

利用SMM漏洞绕过操作系统安全限制

[复制链接]

735

主题

1102

回帖

3076

牛毛

二级牛人

积分
3096
QQ
发表于 2009-7-7 17:51:18 | 显示全部楼层 |阅读模式 来自 山东省威海市
利用SMM漏洞绕过操作系统安全限制
1引言
        操作系统的设计者们可能没有预料到,他们设计的系统中未采用的一些硬件特性竟然会成为威胁系统安全模型的严重隐患。接下来,我们将向大家展示一些出乎他们意料之外的利用代码,来说明这些合法但是罕为人使用的硬件特性,同样可以为攻击者所利用,突破系统的安全限制。
        在本文中,我们将利用i386平台的SMM(System Management Mode,系统管理模式)漏洞,来绕过一个以安全而著称的操作系统——OpenBSD上的安全保护函数的限制。通常在OpenBSD中可以使用所谓的“安全级”(secure levels)来限制超级用户的权限。尽管如此,我们仍然可以让超级用户取得额外的用户特权。随后还会举一个例子,具有超级用户权限的攻击者将如何利用合法的硬件功能调用来降低系统的安全级别。我们将这种攻击手段公之于众的目的,在于引起操作系统设计人员的高度重视,必须谨慎考虑系统基于的硬件体系结构和安全模型之间的关系。同样,硬件开发人员也必须为软件开发者提供硬件上高效的、可管理的安全功能。在我们的示例中,处理器和芯片组方面并无实现上的缺陷(flaw),它们的行为都如我们的预期所愿。然而真正的脆弱点来自于它们的某些功能,被攻击者利用后会给恶意程序带来很大的便利。
        我们已经将文中的技术细节最大限度的趋于一般化,在任何使用Pentium或P6系列处理,知晓SMM模式的芯片组的系统上都具有较好的通用性。文章的第2部分,我们简单的描述一下Pentium处理器的SMM模式,第3部分介绍攻击者如何利用这种处理器模式,第4部分,来讨论什么样的操作系统会受此影响。对OpenBSD攻击的实证研究放在第5部分。第6,将此攻击手段移植到其他操作系统,第7,一些防范措施,最后是本文的结论。

2 系统管理模式System Management Mode
2.1 Pentiumr和P6系列的操作模式
        根据制造商Intel的相关文档,该类型处理器有四种操作模式。在启动顺序中,处理器先以实地址模式(real- address mode)运行,然后切换到保护模式(protected mode)。前者是一种在启动时常用的、16位的地址寻址模式,而保护模式为32位的。目前所有的现代操作系统,如Linux、Windows和Unix等,都是运行在保护模式。保护模式提供了不同的处理器权限,就是所谓的“ring”,从ring0到ring3,为最高权限到最低权限的过渡。标准操作系统中的内核代码都是运行在ring0级别,相对的用户程序运行于ring3,这是为了防止用户程序直接和内核代码及数据的交互所考虑的。一般情况下,关键的操作都在ring0执行,用户程序只能按照需求,通过系统调用才能请求内核服务。为此,保护模式提供了相当丰富的安全机制,例如代码分段和内存分页等。相对实模式1GB的物理内存寻址能力,其32位地址空间,最多可以支持4GB物理内存寻址。另一种模式是虚拟8086(Virtual 8086)模式,相对用得较少,用来提供8086程序的兼容性,典型的有DOS下的应用程序。最后是SMM模式,顾名思义,被用来执行硬件触发的系统管理操作,其提供了相当便捷的电源管理和系统硬件控制的功能。
        图1展示了四种模式之间的转换关系,从保护模式转到实模式需要ring0特权级,而保护模式和虚拟8086之间的转换只能在中断处理或特殊的硬件任务环境下才能完成。

图1.四种处理器模式的转换操作
2.2 SMM基础
        进入SMM模式的方法只有一个,即判断在其他模式中是否产生了一个硬件模式中断,称之为“系统管理中断”(System Management Interrupt,SMI)。然后,也只有唯一的方法离开SMM——使用机器指令rsm。为了还原到中断发生之前的状态,当进入到SMM模式以后,处理器上下文被存储,离开时再恢复回来。言外之意,进入了SMM模式将冻结整个操作系统的执行,并让处理器处于一种特殊的执行上下文中。分页机制在SMM中是不允许的,虽然只是16位的寻址模式,但使用了所谓的“内存扩展寻址”(memory extension addressing)技术,仍然可以访问4GB的物理存储空间,而且还可以毫无限制的访问本机的所有端口。就此看来,SMM的权限和操作系统代码运行的ring0级非常类似。
进入SMM,处理器将默认的执行代码和程序状态存储在一个专有的内存区域中,称为SMRAM,它通常的位置在SMBASE和SMBASE+0x1FFFF之间的地方,如果使用了Extended SMRAM,其范围还要更大一些。SMBASE的默认值为0x30000,但是现代的芯片组可能将其重定向到0xA0000。如果是前一种情况,这块内存只能由SMM访问,但是后者,0xA0000碰巧也是视频卡内存映射I/O端口的基地址。这意味着芯片组必须能够正确解码对0xA0000-0xBFFFF范围的内存访问。当处理器未处于SMM时,芯片组将内存访问信号导向视频卡(如果此时没有设置D_OPEN位的话,详细的后面再介绍),否则芯片组会将其视作SMRAM内存访问。在我们所测试过的PC上,BIOS制造商都将SMRAM定位到0xA0000,因此我们可以将此视为目标系统的默认情况。

图2.P4体系结构下访问视频卡RAM的内存范围
2.3 SMM攻击的价值
        站在攻击者的立场,从保护模式转换到SMM,将可以修改任意内存区域,在内核中安装后门或者悄悄的修改安全参数,是具有相当吸引力的。攻击者还可以通过修改已存储的寄存器状态来改变当前任务的硬件设置。即使回到保护模式,操作系统也意识不到危险已经发生。
        但是实现上述有两个难点,一是攻击者必须在主板上触发一个SMI中断,这种中断并非由普通的机器中断指令“int”产生;第二,进入SMM后,处理器总是跳转到物理地址SMBASE+0x8000处。攻击者想要在SMM中执行恶意代码,需要先在非SMM模式下,覆盖SMRAM内存区,写入自己的将要被执行的程序。呵呵,这看似是不可能的吧。

3在保护模式或实模式中访问SMRAM
3.1 产生SMI
        SMI信号来源于主板上的硬件中断,其唯一目的便是切换处理器状态到SMM模式。有时如果处理器温度过高,超过了一个警戒值,就有可能产生SMI信号,随即触发主板生产厂商预置的处理例程。
        触发SMI有多种方法,但是唯独不能由软件中断指令所引起。在这过程中,芯片组将SMI信号传递到处理器,并引发多种事件。具体的事件和芯片组及其设置有关。某些情况下,I/O APICs(输入输出高级可编程中断控制器)也可承担SMI信号转发的任务,但就我们所了解,目前主板集成的APIC还尚未具备此功能。
        芯片组中有两个比较重要的SMI寄存器, SMI_EN和SMI_STS。前者决定哪些设备能够产生SMI中断,而且SMI_EN的最低有效位是一个“全局使能”开关,指明是否允许产生SMI中断。SMI_STS是一个“写入-清除”寄存器,用来追踪当前产生SMI中断的设备。该寄存器不提供重置操作,因此要由SMM软件来自行清理和设置。

图3. SMI_EN,SMI_STS,PMBASE寄存器,以及SMRAM控制寄存器
        我们可以通过传统的I/O指令,in和out,来访问上述两个寄存器,而且它们的位置分别在PMBASE+0x30和PMBASE+0x34的地方。PMBASE中存储的数据,又可以通过标准的PCI配置机制来读取或修改,这要用到端口0xCF8和端口0xCFC,前者作为地址寄存器,后者作为数据寄存器。要修改PCI配置寄存器时,我们将其地址发送到0xCF8端口。这个地址包括了总线,设备和函数的编号,还有一个偏移值。例如,可以用总线0,设备0x1F,函数0和偏移0x40来访问。然后就可以通过0xCFC端口读出或者写入数据。
        为了产生SMI中断,第一步首先需要设置SMI_EN的最低有效位。有的BIOS会自动设置,但还是要先检查一下,然后就可以用最合适的方法产生SMI了。我们在实验中找到了一种较为方便的SMI触发方法:访问可编程I/O端口0xB2即可,它是高级电源管理寄存器。不过这个方法还需要SMI_EN的Bit 5被置位才行。当然了,上述一切需要有I/O端口的访问权限才行。
3.2替换SMM处理程序
        如果计算机真的产生了一个SMI中断,那我们也很难注意到它。处理器保存上下文,执行默认的代码,最后再恢复现场,并没有引起外部多大的变动。为了利用SMM获得对主机系统的全权控制,我们就需要在触发SMI之前,对默认的SMI处理句柄作一些必要的修改。如前所述,处理句柄位于0xA8000内存的地方,通常情况下,对此的访问都是转向视频卡的,只有当处理器位于SMM时,才能访问到SMRAM这块区域。看起来这是一个相当棘手的问题,我们缺少一种能够在进入SMM之前访问SMRAM的方法。
        然而,面包总是会有的。芯片组中的北桥(Northbridge)芯片,也叫做 Memory Controller Hub,MCH,是我们的希望之所在。其中有一个8位寄存器,称为“SMRAM控制寄存器”,只要设置正确,就可以在非SMM中访问SMRAM内存区。准确的说,如果该控制寄存器的bit 6,D_OPEN 位被置位,对 0xA0000-0xBFFFF的访问都会被导向SMRAM。对待D_OPEN 位应该慎之又慎,因为还有显示子系统也共享目的内存区,否则可能导致很多莫名奇妙的系统崩溃错误。
         SMRAM控制寄存器中的另一个重要bit是bit 4,D_LCK位。置位时,可以锁定SMRAM控制寄存器,这样就不能改变其中的数据了。而且该bit直到系统重启时才能被清除,因此也经常被作为保护SMRAM控制寄存器被配置的手段之一。我们可以用3.1节提到的PCI配置机制来访问SMRAM控制寄存器,总线0,设备0,函数0,偏移0x9C
        在执行普通操作的时候, D_OPEN是没有被置位的,那显示目的的访问可以执行。如果BIOS在启动过程中设置了D_LCK位,那在保护模式就不可能再访问SMRAM了,只能重启,或者换一台机器。从我们测试的情况看来,万幸D_LCK都没有置位。在替换SMM处理句柄时,先检查D_LCK,再设置 D_OPEN,然后在0xA0000和0xBFFFF之间注入新的SMM例程就可以了。

4 SMM和操作系统
4.1取得I/O端口权限
        我们上述的各项步骤都是通过访问I/O端口和物理内存,才利用到了SMM的各项便利。为了替换SMI处理句柄,要至少能访问0xCF8和0xCFC两个端口。在Linux或Unix中,这需要使用iopl()系统调用,而且其仅对超级用户开放。也就是说,要具有超级用户的权限才可以放置我们的代码。在大多数的Linux系统中,取得超级用户权限也意味着对/dev/mem这样的虚拟设备有了完全的写访问能力,可以寻址整个物理内存地址空间。这样的话,就没有必要再绕SMM的弯子获得更多权限了,因为攻击者已经得到了他所想要的最大权限,攻击的目的已经达到。然而对于更多的安全操作系统,超级用户并不意味着你可以访问物理内存。毕竟对于以非本地计算机管理为目的超级用户来说,给予他们过多的权限是十分危险的。此时,SMM漏洞利用才显示出它的价值。

4.2 OpenBSD
        OpenBSD是一个基于BSD的,以安全而著称的操作系统。在此系统上,可以使用前面提到的安全级别来限制超级用户的特权使用。设计者们用一个整数来表示安全级别,取值范围是-1至2。当安全级为-1时,安全级别最低,为2时是最高。这里有一个关键,当系统运行在安全级1或者更高时,是不可能降低当前安全级的。也就是说,Root用户可以提升安全级,但不能降低。如果在启动时设置安全级为2,要降低级别,除了重启系统别无他法。在安全级2,用户对/dev/mem只能读取,即使超级用户也不能向物理内存随意写入数据。然而,此时执行SMM漏洞利用的代码却可以扩展用户的特权。
我们将目标系统定为运行在安全级2的OpenBSD系统。在此不会有显示服务器(X Server)程序读写/dev/mem的干扰。虽然在Linux下它是这么干的,但这里X Server使用/dev/xf86,仅使用和视频卡内存映射I/O范围内的物理内存,而其他的区域该设备都不可访问。而且任何时刻系统中仅有一个进程持有处于打开状态的/dev/xf86设备。这也意味着如果X Server还在运行,那它将无法再次打开这个设备。最后还要说明一点,如果本地管理员觉得不需要使用图形模式,他可能会将系统变量allowaperture设为0。那么任何人都不能再使用/dev/xf86,iopl()也没有效果了。
        我们的例子中假设allowaperture为非零值,即本地用户需要使用图形模式。在攻击之前如果显示服务器还在运行,需要先将其关闭,才能访问到/dev/xf86设备。为了覆盖处理例程成功,用户只需要使用open()和mmap(),映射从0xA8000开始的物理内存,设置SMRAM 控制寄存器中的D_OPEN位,写入新的句柄,再清除D_OPEN位就行了。随后,触发的SMI就可以调用我们的程序执行。

5 OpenBSD攻击的实证研究
        我们将目标OpenBSD看作一个“黑盒子”,篇幅所限,对相关的硬件也不再作什么前导知识的介绍。在读取芯片组和PCI控制寄存器之前,我们先检查SMI是否被允许。系统设置SMBASE为 0xA0000,而且PCI配置没有锁定。
        漏洞允许超级用户进入SMM,并访问整个物理内存。在我们的例子中,获得特权仅仅是为了降低系统的安全级。结合前文所述,攻击的具体方法如下:
1. 以超级用户身份,检查X Server是否在运行,如果是,则将其进程结束。
2. 读取PMBASE的值,打开SMI使能标志。
3. 设置SMRAM控制寄存器的D_OPEN位。
4. 打开“/dev/xf86”,将0xA8000 开始的一页物理内存映射到当前进程的虚拟地址空间。
5. 使用映射内存写入新的SMI处理程序。
6. 清除D_OPEN位。
7. 访问可编程I/O端口0xB2,以触发一个SMI中断。
8. 检查后发现,安全级别确实已经降低。
        上述步骤的代码放在文章附件里,包括了步骤3到7的实现。预定的SMI处理句柄将系统安全级降为-1,并修改了保护模式指令指针寄存器(EIP)的值,最后再离开SMM。所以SMI将返回到一个保护模式中从未调用过的函数里。这样,我们的句柄必须首先在物理内存中正确定位存放着安全级别的变量,“nm /bsd | grep secruelevel”命令可以在当前内核中确定其虚拟地址。因为一个内核对象的虚拟地址相对其物理地址有 0xd0000000的偏移,此时再来计算其物理地址就相当明了了。

6 其他易受攻击的操作系统
        上一节中介绍的攻击方法对NetBSD同样适用,只要是安装了/dev/xf86驱动的操作系统都会受此影响。攻击者以此降低了系统的安全级别。更进一步说,任何给予了攻击者I/O端口访问权限的操作系统都是不安全的,包括Linux等在内,写访问图形部件的内存有可能让攻击者取得内核权限。如果我们信任具有上述两种权限的组件或者用户,那也就等同于放心的将内核权限拱手交给了他们。而在事实面前也不得不承认,在对待图形显示服务器上,我们确实是这样做的。

7 防范措施
        我们刚刚描述的这次攻击可以看作是代码注入的一个特例,一般情况下,原有的那些针对代码注入的软件保护措施在这里丝毫不起作用,因为它们的目标——缓冲区溢出,和SMM漏洞的机理截然不同。就算使用NX标志(No eXecute标志,为了安全原因,被CPU用来将内存区域显示划分为指令区与数据区),或者压缩数据段的长度,以阻止shellcode覆盖,同样无济于事。而这一切的原因都在于只要/dev/xf86设备映射完成,SMRAM就处在一个合法的用户内存空间当中,而进入SMM后,所有保护模式的安全机制都将免谈。在保证功能正确的情况下,扰乱操作系统内部某些代码的组织结构,可能会大大增加攻击者利用SMM的难度,但这需要对操作系统代码或处理器结构作出重大改动,看起来似乎不太合算。
        有些人想到是否可以使用即时内存加密技术来对抗SMM漏洞,可惜,它同样是不起作用的。虽然如此,但基于报文鉴别码(Message Authentication Codes ,MAC)或者签名机制的加密技术却有助于SMI处理句柄可靠性和完整性的保持。因此,我们必须在处理器中妥善保管好密钥或者证书之类的,以便检验。然而这个方法也不太经济,需要处理器或者主板结构上的较大变动。
        这里还有其他的一些方法。很容易想到的就是尽早设置 D_LCK位。理想情况下,这个工作是由BIOS来做的,然而似乎大多数的BIOS都失职了。在将来的PC中让BIOS克敬职守算是亡羊补牢,为时未完,但要让目前PC的BIOS都升级到安全要求恐怕就比较具有挑战性了。一种替代的方法是更新操作系统,在需要的时候让系统自动设置D_LCK位。
        在OpenBSD的特例中,最简便的应对方法就是本地管理员永久的设置allowaperture变量为0值。这可以防止系统内其他进程向 X server发送危险信号,但是init进程除外。
        利用SMM扩展权限的例子肯定不止这一个了,其他基于PIO(Programmable Input Output,可编程输入输出)控制的功能也可用来达到此目的。由此观之,长远的解决方案还是让操作系统有效的限制ring3代码访问PIO寄存器的能力。这种方案仅能在确实需要PIO能力的应用程序上实施。比如,X Server的设计者可以将显示服务器移动到一个更为安全的环境中,将X Server分为两个不同的部分:一个需要对PIO的访问,或者要求更多的权限,运行在内核模式,对运行在用户空间的另一半提供必要的抽象。剩下的仍然在用户空间,需要特定权限时和内核部分交互就可以了。

8结论
        本文介绍了一种滥用机器硬件功能而威胁系统安全的新方法和新手段。反观,这也向软硬件设计人员提出了一个新的要求,需要谨慎分析和处理硬件功能与系统安全之间的区别与联系。SMM漏洞的适用性很广,即使是OpenBSD这样的操作系统也未能幸免。或许正是由于设计人员间的沟通不足,无意中的疏忽正好暴露了系统的一个致命弱点。
        虽然我们的攻击代码是在OpenBSD上实现的,但原理都大致相同,稍作修改也可以在其他基于BSD或者Linux的系统上实现。可能通过SMM扩大用户权限在Linux上的意义不大,因为系统一般并不限制root用户加载内核模块或者写访问内存的能力。但是换言之,如通过安全级,安全标签等等,对用户有权限最小化和权限分离机制的系统,就不得不面对处理器SMM模式的问题。如果检查不到位,安全限制就有可能形同虚设。
        本文还有另外一个目的,意在说明给予超级用户,甚至所有用户完全的I/O端口的访问权限是极其危险的。文中漏洞的利用正是有了I/O访问才得以实现。在将来的工作中,我们还将进一步分析处理器和芯片组功能对操作系统安全的影响,也但愿技术的发展能将这二者更加紧密、有机的结合起来。
您需要登录后才可以回帖 登录 | 开放注册

本版积分规则

帮助|Archiver|小黑屋|通信管理局专项备案号:[2008]238号|NB5社区 ( 皖ICP备08004151号;皖公网安备34010402700514号 )

GMT+8, 2025-4-25 12:05 , Processed in 0.210384 second(s), 32 queries .

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表