目录

    • 一、系统安全现状
    • 二、攻防演化
    • 三、代码注入攻防
      • 1、通过内核漏洞
      • 2、系统控制能力大
      • 3、多见于早期Linux
      • 4、内核代码注入防护
      • 5、通过内核页表来实现
      • 6、通过隔离环境保护内核页表
    • 四、内核代码重用攻击
    • 五、内核数据攻击
      • 1、控制数据被保护后,攻击者提出非控制数据攻击
      • 2、非控制数据防护
    • 六、内核攻防演化
      • 1、攻击演化
      • 2、防护演化
      • 3、防护方案的滞后性
      • 4、最近几年的攻击方式总结
    • 七、容器介绍
      • 1、什么是容器
      • 2、 操作系统级虚拟化
      • 3、具有效率高、启动快、配置灵活等特点
      • 3、由namespaces负责隔离
      • 4、由control groups进行限制
      • 5、容器资源隔离
      • 6、容器资源隔离安全性分析
    • 八、内存计数问题
      • 1、内核依赖memcg对内存进行计数
      • 2、memcg未经系统性安全分析,存在安全隐患
      • 3、我们的工作
      • 4、发现了policy design中导致的计数缺失的问题
      • 5、设计基于编译器的自动化分析工具
      • 6、内核安全性在对抗中大幅提升,但对数据攻击防护依然不足
      • 7、容器场景给内核带来了新的机遇,也带来了新的安全挑战

一、系统安全现状

首先我们来看一下系统安全,特别是系统安全的现状,这是Linux2008~2019年的内核代码的数量,然后到2019年已经超过2300万行,现在我们的最新统计数据是将近2800万行代码。

另一方面如果我们只看Linux内核,我们觉得它的代码量挺高的,但是我们如果把它放到整个安卓的生态里面来看,其实它只是在很小的一部分,在Linux内核之上,还有Hal hardware abstraction there这一层,上面还有Android的run time层,再往上面有安装的framework,还有applications

二、攻防演化

代码量跟bug的数量或者说跟漏洞的数量它是成正比的,代码量越多,它的bug漏洞数目也会越大,所以这是Linux内核的一些现状。在最近一些年,它里面的bug数量每年都超过125,这都是Linux内核里边可以被利用的bug数量,代码量巨大就会导致新的漏洞,所以软件漏洞无法避免,这些软件漏洞往往会被攻击者利用,这就会产生新型的攻击。

另一方面,新型的攻击又催生了新型的防护,所以对操作系统内核的攻防是在不断的对抗中演化升级的,它的攻防不是静态的,不是一下子就能全部防住的,它是在不断对抗中演化升级,所以没有绝对安全的系统,也没有绝对强的攻击手段,他们都是相对在演化,所以我们有一张这样的图,如果来看我们攻防演化,我们按照这个手段对它进行分类的话,首先是代码注入攻击,然后防护代码注入攻击, 研究人员提出了带数据不可执行,然后对进行防护。

攻击者发现他的攻击手段被防护了之后,进而提出了代码重用攻击,然后安全研究人员又提出了新型的防护,叫控制类完整性进行部分防护。在这之后攻击者又提出了数据攻击,而现在我们又提出了这个数据有完整性一些保护。

三、代码注入攻防

1、通过内核漏洞

  • 篡改已有代码text section
  • 注入新的代码
  • 或者跳到用户代码,比如jump-to-user

2、系统控制能力大

  • 可执行新代码
  • 危害大

3、多见于早期Linux

  • 比如Kernel Text RWX (Android 2013)

4、内核代码注入防护

  • 保护已有代码W^X
  • 硬件支持,杜绝注入
  • 数据不可执行(2001 XN ARM; NX AMD)
  • 特权不可执行(2011 SMEP Intel; PXN ARM)

5、通过内核页表来实现

  • 在内核页表设置相应的保护位,实现保护
  • 多数Android设备, 包含Google Pixel
  • 防御性弱,内核页表被改掉即失效
  • 对内核页表没有保护
  • 攻击者可篡改页表,去掉保护
  • 进而篡改代码

6、通过隔离环境保护内核页表

  • 通过隔离环境,避免内核漏洞影响
  • 实现了纵深防御defense-in-depth

四、内核代码重用攻击

无法注入新代码,重用已有代码,通过篡改控制流,拼接已有函数片段,实现攻击函数,也被称为控制流劫持攻击。

五、内核数据攻击

1、控制数据被保护后,攻击者提出非控制数据攻击

  1. 返回地址和函数指针以外的数据
  2. Data-oriented programming
  3. 影响关键的安全特性
  4. 仅利用非控制数据攻击做到内核提权

2、非控制数据防护

非控制数据攻击的一个例子就是s一Linux绕过,在Linux内核的代码44.4版本里发现一个全局变量,如果是0,就会永远是真,所以就永远绕过,攻击者一般拿到这个之后,获得了内存的读写权限,首先把变量写成0,Linux的所有检查都会绕过,但是现在对于非控制数据还没有很好的有效防护,所以现在主流的操作系统也都没有部署对数据攻击的有效防护。

六、内核攻防演化

1、攻击演化

它的攻击复杂性在指数增进,同时它的隐蔽性也在增加,代码注入工具很容易被检测,因为它改了代码或者增加了代码,代码重用攻击只改了written Reiss的方向,所以它已经比较难检测,而数据攻击就更难检测,这么多数据,你根本不知道哪些被篡改。

虽然这个攻击的难度在增加,但对于我们比较有利的是它的控制能力却在减少,代码注入攻击能力最强,代码注入攻击可以拼接代码片段,也可以做到图例完整。

数据攻击就只能通过筛选数据,并且你的攻击范围只能是数据控制的一些代码,所以它的控制能力在减弱,但是它依然能够入侵操作系统内核,依然能够做到权限提升,所以数据攻击危害性还是很大。

2、防护演化

防护方面的演化,每一个攻击出来,首先都会提出一些防护的方案和解决思路,并且一般都是通过一些学术论文发表,大家提出的防护方案,后续这些学术的原型软件的方案通过沉淀,通过不断的优化,硬件厂商会把它做到硬件化,比如说后面会有一些AMD或者intel,会把它真正的实现到硬件里面来提供支持。

硬件首先能提高安全性,其次能减少性能开销,所以一般硬件被防护机制支持后,这种安全机制一般会大规模的商用,这就是防护的研发趋势,从软件到硬件,从学术界的原型到产业界的实用方案。

3、防护方案的滞后性

对于代码注入攻击,最早是在1988年出现的, 到2001年才有硬件的防护方案,所以滞后13年,代码重用攻击滞后17年,而数据攻击到现在还没有很好的防护方案,所以它的滞后性肯定会更多。

4、最近几年的攻击方式总结

下面对攻击方法进行一个总结,这是最近几年的一些总结,蓝色的是代码重用攻击,红色的是数据攻击。这里面我们可以看到代码注入攻击已经很少了,一些比较有名的论文,都是基于代码重用攻击或者数据攻击的。

这里面每一个有图标的都是一个真实的攻击案例。

我们总结一下防御的方法,防御的方法就是内存的安全问题,主要可以归为两类,一个是越界的独,一个是越界的写。

越界的读,如果它读了不该读到的数据,就会造成一个Information。越界的写,如果他写代码的话,它就是代码输入攻击,如果他写控制数据,它就是代码重用攻击,也要控制这个攻击,如果他写非控制数据的话,叫面向数据,这是传统的系统内核攻防的演化,现在这个容器应用更加广泛了,容操系统在容器的场景下,面临一些特殊的安全挑战。

七、容器介绍

1、什么是容器

容器是操作系统级虚拟化,它是由同一个内核虚拟出来多个用户空间的实例,每个用户空间的实例,不需要维护单纯的内核,用户空间的实例,也叫容器实例,它不用单独维护内核,所以它效率高,启动快,并且配置比较灵活,会被广泛应用于代码。

2、 操作系统级虚拟化

由同一内核虚拟出多个用户空间实例,无需维护单独内核

3、具有效率高、启动快、配置灵活等特点

3、由namespaces负责隔离

首先是提供了namespace,它负责隔离,namespace相当于镜像。如果我们说一种资源,它被namespace的,就说这个资源在容器看到的跟 Linux内核外边看到的是不一样的,相当于给容器一个单独的镜像,现在内核支持了8种namespace,这叫资源的限制,叫control group,它可以限制CPU,可以限制内存,可以限制一些设备资源,它可以限制你用了多少CPU,用了多少内存,对IO的访问速度是多少。

4、由control groups进行限制

  • 当前内核支持13种cgroups
  • 主要用于限制CPU、内存和设备资源

5、容器资源隔离

(1)本质是基于进程的资源隔离

  • +namespaces and cgroups

(2)进程能access哪些内核资源

  • Kernel text
  • Global data
  • Heap
  • Stack
  • Kernel provides 300+ syscalls

6、容器资源隔离安全性分析

  1. 当前容器注重限制物理资源,忽略抽象资源,如内核变量
  2. 我们发现这些抽象资源同样可以被DoS攻击
  3. 例如打开大量文件,耗尽nr_files
  4. 所有新打开文件操作均会失败,导致无法运行新程序

这些内核数据同样决定操作系统功能的可用性,容易导致DoS攻击,内核data dependency复杂,难以彻底解决DoS问题,高安全性要求场景建议使用虚拟机隔离。

八、内存计数问题

1、内核依赖memcg对内存进行计数

2、memcg未经系统性安全分析,存在安全隐患

3、我们的工作

  1. 形式化定义了内存计数的步骤
  2. 分析了policy design的问题
  3. 设计自动化工具分析implementation问题

4、发现了policy design中导致的计数缺失的问题

攻击者可以轻易突破memcg内存限制

5、设计基于编译器的自动化分析工具

policy implementation进行系统性分析

6、内核安全性在对抗中大幅提升,但对数据攻击防护依然不足

  1. 代码注入攻击
  2. 代码重用攻击
  3. 数据攻击

7、容器场景给内核带来了新的机遇,也带来了新的安全挑战

  1. 抽象资源攻击
  2. 内存计数问题

上一篇:【Java 多线程 7】通过socket、多线程、动态代理、反射 实现RPC远程方法调用

下一篇:Java学习路线总结,搬砖工逆袭Java架构师