DirtyCred 论文阅读笔记

ABSTRACT in my word

Contributions

  • 提出了一种新的,通用的exploitation方法DirtyCred ,能够绕过先行的大部分内核环节策略完成提权利用;

  • 使用了一系列典型的Linux内核漏洞进行验证,证明了DirtyCred可以适用于大部分漏洞;

  • 提出了将特权进程的credentials 与一般进程存储在不同的区域的缓解策略,并进行测试发现产生的overhead可以忽略不计;

Threat Model

在可以直接接触Linux系统环境中,利用内核堆内存漏洞,完成对自己权限的权限提升利用;要求Linux系统尽可能开启安全以及漏洞缓解机制(包括KASLR, SMAP, SMEP,CFI,KPTI等)

Directory

  • Section 2 introduces the background needed for this research and discusses the
    threat model.

    • 2.1 Credentials in Linux kernel

    • 2.2 Kernel Heap Memory Management

    • 2.3 Threat Model

  • Section 3 introduces the high-level idea of DirtyCred and summarizes the technical challenges that DirtyCred confronts

  • Section 4 pivoting vulnerability capability (Step 1 of DirtyCred)

    • 4.1 Pivoting OOB & UAF Write

    • 4.2 Pivoting DF

  • Section 5 extending Time Window (Step 2 of DirtyCred)

  • Section 6 allocating privileged object (Step 3 of DirtyCred)

  • Section 7 evaluates the effectiveness of the proposed exploitation approach on real-world Linux kernel vulnerabilities. (简单过一下就行)

  • Section 8 introduces a new defense mechanism and evaluates its performance on standard benchmarks

Key Notes

2.2 [内存管理] 两种cache管理模式

  • 通用缓存(Generic Caches) : 在Linux 内核中如果没有指定分配区域,默认会被分配到通用缓存中,按照不同的cache size进行分配。 这部分的地址是可以被共享和重复使用的;

  • 专用缓存(Dedicated Caches) : 为了性能和安全性考虑将一部分对象分配到专用的缓存中,这部分内存区域与通用缓存不共享;[缓存隔离]

3.1 以CVE-2021-4154为例介绍工作流程

首先,CVE-2021-4154可以让Linux内核直接释放一个仍然可能被使用的File对象. 漏洞利用流程图如下:

Figure-1.png

按照顺序:

  1. DirtyCred 进程打开一个可写文件(如/tmp/x), 并尝试向其中写入内容,内核会首先检查文件是否有写权限以及当前文件位置是否允许被写入;

  2. 在向文件写入内容之前,触发漏洞释放掉文件文件对象

  3. 打开一个只读文件(如/etc/passwd) , 由于Linux系统内存分配机制会被分配到刚刚被释放的file对象,继续写操作即可向只读文件中写入内容;

  4. 写入如hacker:x:0:0:root:/:/bin/sh 即可创建一个root用户,完成提权目标

4-1 Pivoting OOB

选取一个包含credential索引指针的的受害对象,让其分配到漏洞对象的后面,通过触发漏洞去劫持, 并通过将最后的4个byte设置为0,来将该指针劫持到credential 对象所在页表的起始位置。同时,认为被劫持的指针随着受害对象的释放而释放;

Figure-2.png

4-2 Pivoting DoubleFree

Figure-3.png

将double free转化成DirtyCred可以利用的形式相对比较复杂,总结来说需要解决如下的问题:

  • 由于cache分离的机制,用于double free的对象通常并不是credential object;

  • 漏洞对象所在的cache大小可能与credential object所在cache的大小不同;

为了解决上述的问题,作者提出了这样的通用转换方案:

  1. 首先在漏洞对象所在的cache中分配大量的对象(占位),并在其中夹杂一个漏洞对象;这样做的目的是后续通过讲cache中所有的对象全部释放来触发内核中的回收机制,来解决cache隔离的问题;

  2. 由于double free的关系,我们可以理解为有两个指针(ptr1, ptr2)同时指向了漏洞对象;首先通过其中一个指针将漏洞对象释放(free ptr1)

  3. 再次申请一个漏洞对象使得有三个指针同时指向一个对象(首个漏洞对象的ptr2,以及新申请漏洞对象的ptr3,ptr4)

  4. 再次通过其中任意一个指针释放掉漏洞对象,并释放掉所有的占位对象;此时,cache会被清空,同时会有两个悬空指针指向cache中的某个位置;

  5. 通过内核的回收机制,让空的cache被用于分配credential object;

  6. 此时由于漏洞对象与credential object大小不一定相同的原因,会导致两个悬空指针指向的位置极可能并不是一个对象的起始位置,导致无法利用;通过其中一个指针释放一次,再触发一次credential object对象分配

  7. 此时,一个double free的漏洞被成功转化成为了一个类似UAF漏洞,后续按照UAF漏洞的利用方式利用即可;

5-EXTENDING TIME WINDOW

利用内核的Userfaultfd & FUSE两种机制,其中Userfaultfd在一些kernel pwn的ctf教程中都有更详细的说明;FUSE(Filesystem in userspace)允许在用户空间响应各种文件操作,通过向内核空间中传入FUSE系统中的文件句柄,访问相关资源的时候,请求就会被回落到攻击者控制的用户空间中,以此来扩充漏洞利用的时间窗口;

6-2 Two ways to allocate privilege object from kernel space

在用户空间,一般权限进程可以通过运行一些带有SUID权限的应用以完成DirtyCred利用中要求的用Privileged Object占用non-Privileged Object要求;

除此之外,作者提供了两种从内核空间申请Privileged Object方案,其核心思想是在内核空间中创建一个线程,大部分的内核线程都是高权限的,以此也可以达到提权的目标;

  • 通过在kernel workqueue中新增一个worker

  • 通过加载内核模块到内核,以此让内核调用usermode api

Reference