CFI in Android Kernel Security ppt略读 - 来自Linux Security Summit USA2018

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/think_ycx/article/details/82182712

目录

一、Android内核漏洞概览

访问控制

seccomp sandboxing

不需要权限在userland就可以被触发的bug

不从userland也可以被触发的bug

内存安全对所有的内核漏洞进行分类

二、CFI(Control Flow Integrity)


记录一下早上(20180828)看的这个ppt,免得白看了。ppt来自Linux Security Summit Aug 2018。
本文很多内容是读ppt的时候的一个记录,如果有理解不对的地方,欢迎指出。
此外,也有少部分内容没有完全理解,以后用到了再看。
ppt原文:https://events.linuxfoundation.jp/wp-content/uploads/2017/11/LSS2018.pdf

一、Android内核漏洞概览

Android中的内核漏洞占据所有Android安全漏洞的三分之一。

目前来说,漏洞缓解机制中达到的效果最好的是减小攻击面。访问控制是减小攻击面的一个具体实现。
Mark Brand - Google Project Zero说目前最有效的漏洞缓解措施已经生效了,大大减少了攻击面:加强的selinux的策略和seccomp sandboxing。

访问控制

这要求攻击者需要在更小的攻击面中找到更多的漏洞。增加访问控制也是成本比较低的,因为访问控制不需要有exp编写经验就可以应用在系统中。
攻击面减小之后导致好处就是,很多kernel vulns在userland是可以被触发的,但是不能被unprivileged进程触发。增加了访问控制机制后(selinux、unix 权限模型、Capabilities),这些漏洞都受到了限制。效果如下图所示:

seccomp sandboxing

seccomp sandboxing是内核隔离的一种实现。
参考资料:seccomp sandboxing是linux kernel2.6.23中引入的安全机制。它能使一个进程进入到一种“安全”运行模式,该模式下的进程只能调用4种系统调用(system calls),即read(), write(), exit()和sigreturn(),否则进程便会被终止。受到的限制是:Seccomp模式的进程不能动态分配内存、不能与其它进程使用共享内存、不能使用新的文件描述符、等等。如果要支持具有丰富功能的应用程序,则需要另外的方法来截获并处理其它系统调用。相关关键词:TOC2TOU、ftrace。来源:https://blog.csdn.net/xpylq/article/details/54138181

从Android O 8.0开始,所有的app都在seccomp sandboxing中运行,因此类似CVE-2017-14140这样的漏洞就受到了限制。参考资料:CVE-2017-14140 4.12.9版本之前,在Linux内核中的move_pages系统调用mm / migrate.c并不检查目标进程的有效uid,使本地攻击者可以学习尽可能使用ASLR的setuid可执行文件的内存布局。来源:https://www.deepin.org/2017/09/25/deepin-security-updates-cve-2017-12134-cve-2017-12153-cve-2017-12154-cve-2017-1000252/

访问控制+seccomp sandboxing是内核提供的两种漏洞缓解机制,目前都起到了很好的效果。

不需要权限在userland就可以被触发的bug

但是,仍然有一些不需要权限在userland就可以被触发的bug。按照触发的来源分类,如下图所示:

按照漏洞的类型分类,如下图所示。

因此内核中中增加了对copy_from_user这些函数的运行时检查。

引入了PAN漏洞缓解机制。效果如下:

  • 组织kernel 直接访问 userland数据

  • 加强的copy from user这些函数的校验

  • Found/fixed multiple instances of kernel directly accessing userspace.(不太明白啥意思)

总之,PAN就是为了让userland过来的数据更加安全的,kernel没权限读userland数据。

不从userland也可以被触发的bug

有了以上的缓解机制还不够(访问控制、seccomp sandboxing、PAN),因为还有一些kernel vulns不从userland也可以被触发。比如,从wifi 蓝牙 usb,个人理解这些属于硬件设备驱动的漏洞,直接运行在kernel land。

总结一下,目前的userland->kernel的防御已经做了以下两点:

  1. kernel提供的攻击面减少的工具:selinux、seccomp sandboxing
  2. 加强的usercopy + PAN 来缓解一些需要访问用户态数据时会发生的漏洞

但最后还有1/3的kernel bugs是由其他的vectors攻击向量导致的。因此还需要类似1、2中这样的工具来帮助我们。

内存安全对所有的内核漏洞进行分类

如果换个角度,根据内存安全对所有的内核漏洞进行分类,分为heap 越界读、heap越界写、stack越界写、heap微初始化,全局变量越界读。

二、CFI(Control Flow Integrity)

从这个角度出发,看看Control Flow Integrity的效果。
what:Control Flow Integrity是通过增加runtime checks来保证控制流在预先计算的图表中。
where: llvm>=3.7中包含了向前的(forward-edge)的CFI,有效保护非预期的分支跳转(indirect branches)。
How:工作的原理是,允许跳转 到 正确类型的有效函数的开始位置。(Allows an indirect branch only to the beginning of a valid function with the correct type.)

实际效果如何呢?55%的非直接的函数调用只有<=5个允许的目标函数去跳转,只有7%有多余100个目标函数去跳转。(不是特别明白,理解为开启了CFI之后的效果是增加了这些东西)

llvm链接时的最佳优化实践如下:

  • llvm的CFI模块会用LTO来决定所有valid call targets。
  • 必须使用llvm的整体的汇编器来进行inline汇编,必须使用LTO-aware的链接器,比如说 GNU gold linker或者是llvm的ld。
  • 目前来说,几乎所有的问题都是由于工具链的兼容性导致的。在测试的几个月中,没有发现内核的稳定性问题。

过程如下:

在今年,第一批的android设备已经刷进了LTO+CFI的kenrel。发现了以下问题:

  • 由于c编译器中允许类型不符的非直接函数调用(indirect calls),导致一些CFI保护失败,这些问题不大,不影响大局,修复了就完事儿了。
  • Cross-DSO CFI support needed for kernel modules.
  • CFI对于indirect calls增加了一个很小的开支(a small overhead),不过由于LTO的存在,尽管加入了CFI,总体的你表现还是不错的。

举个函数指针类型不符的例子,类似这些函数都得patch。

再举个例子(example continued):CFI check, slowpath for cross-DSO(不明白啥意思)。如果target address是允许的才返回。

如果target address有问题,那么CFI check失败,kernel panic。如果处于调试模式,permissive mode下会产生一个warning。panic信息如下:

如果你想要开启CFI,kernel 4.9和kernel4.14中开启如下两个选项,如果要调试,开启CONFIG_CFI_PERMISSIVE=y。

最后,未来的工作有2点:

  1. CFI仅仅保护了 indirect branches. LLVM’s Shadow Call Stack 会保护返回地址。
  2. GNU的gold linker有很多问题,未来会切换到llvm的 lld linker。

看完的感受是:Days become harder for android kernel pwners. 要学的太多了。。

猜你喜欢

转载自blog.csdn.net/think_ycx/article/details/82182712