脏牛漏洞提权原理

1. 什么是写时复制(CoW)?

在 Linux 系统中,当一个进程需要复制一个文件或共享内存区域时,内核并不会立刻为新进程分配独立的内存空间并复制数据。相反,它会让两个进程共享同一块物理内存

只有当其中一个进程尝试修改这块内存中的数据时,内核才会触发“写时复制”机制:

  • 内核会为这个正在尝试写入的进程创建一个新的物理内存副本
  • 这样,原始进程的数据保持不变,而新进程可以在自己的私有内存副本上进行修改,而互不影响

这个机制极大地节省了内存和时间,提高了系统的效率

2. 漏洞是如何产生的?

“脏牛”漏洞的本质就在于写时复制(CoW)机制的一个缺陷

当一个非特权用户尝试访问一个只读文件(例如 /etc/passwd)时,内核会映射这个文件的内存页。按照 CoW 机制,用户无法修改它

然而,内核在处理以下两个操作时,存在一个竞争条件

  • 操作一: 一个线程使用 madvise(MADV_DONTNEED) 系统调用来丢弃一个内存页。这个调用告诉内核:我不需要这个页了,你可以把它从内存中释放掉
  • 操作二: 另一个线程尝试执行写入操作,触发 CoW 机制,申请一个新的私有内存页

正常的流程应该是:如果一个线程在尝试写入,内核会先为其分配新的内存,然后再进行写入。但是,这个漏洞的巧妙之处在于,通过精巧地控制这两个操作的执行时机,可以制造出一个“时间窗口”

攻击者利用这个时间窗口,在内核准备为写入操作分配新内存之前,通过 madvise() 使得内核错误地取消了 CoW 的正常流程。结果是,内核没有为写入操作创建一个私有的内存副本,而是直接在原始的只读内存页上进行了写入

3. 如何利用这个漏洞?

攻击者利用这个漏洞的流程通常如下:

  1. 选择目标文件: 攻击者选择一个具有 root 权限的只读文件,例如 /etc/passwd,该文件包含了系统用户的账户信息
  2. 多线程并发: 攻击者启动两个线程,一个线程不断地尝试对 /etc/passwd 进行写入操作(例如,写入一个新的 root 用户账户),另一个线程则持续调用 madvise() 来触发竞争条件
  3. 成功写入: 在竞争条件被触发的瞬间,写入操作会绕过 CoW 机制,直接修改 /etc/passwd 的内存内容
  4. 获取权限: 攻击者随后会利用修改后的文件,通过新的 root 用户账户成功登录系统,从而获得 root 权限
Copyright © 版权信息 all right reserved,powered by Gitbook该文件修订时间: 2025-09-25 03:12:58

results matching ""

    No results matching ""