8. Dirty COW

[toc]

前言

来源:《Computer Security》A Hands-on Approacharrow-up-right — Wenliang Du

所有的代码/文档见github:https://github.com/da1234cao/computer_securityarrow-up-right

书上的内容介绍比较简单,这篇文档也是如此。

当然,也可以参考同类有些难度的文章(这两篇文章,我没有看):

CVE-2016-5195漏洞分析与复现arrow-up-right利用dirty cow(脏牛)漏洞的提权尝试 arrow-up-right

1. 摘要&&总结

偷个懒。。

Dirty Cow(CVE-2016-5195)是一个内核竞争提权漏洞,之前阿里云安全团队在先知已经有一份漏洞报告脏牛(Dirty COW)漏洞分析报告——【CVE-2016-5195】arrow-up-right,这里我对漏洞的函数调用链和一些细节做了补充,第一次分析Linux kernel CVE,个人对内核的很多机制不太熟,文章有问题的地方恳请各位师傅不吝赐教。

image-20200628075338240

2. 准备工作

在这之前,需要理解竞争条件漏洞,参考:Race_Condition_Vulnerabilityarrow-up-right

2.1 mmap函数

参考:C语言mmap()函数:建立内存映射arrow-up-right + man mmap + mmap和常规文件操作的区别arrow-up-right + Cache 和 Buffer 都是缓存,主要区别是什么?arrow-up-right

mmap和常规文件操作的区别arrow-up-right 介绍的有点问题,注意它的评论区。我也没有清楚明白,暂时不妨碍理解罢了。

2.1.1 mmap函数应用

我们先看看该函数如何使用,再谈其背后的机制。

2.2.2 mmap和常规文件操作的区别

  1. read()和write()系统调用,都将陷入内核,将数据从硬盘-->页缓冲区-->内核空间;再从内核空间拷贝到用户空间。(页缓存,解决IO读取慢的问题)

  2. mmap函数,也会导致陷入内核,但它仅建立用户虚拟地址空间和文件的映射关系(虚拟地址映射到物理地址,物理页具体内容没有加载;)。当进程访问这片内存的时候,发生缺页中断,将文件内容-->页缓冲区-->y用户态物理空间。

  3. mmap之所以快,是因为建立了物理页到用户进程的虚地址空间映射,以读取文件为例,避免了页从内核态拷贝到用户态。

  4. 总体来说,mmap在进程的虚拟地址空间中创建一个新的映射。简而言之,它将大块文件/设备内存/任何内容映射到进程的空间,以便仅通过访问内存即可直接访问内容。

  5. 真的明白了吗?非也。上面的观点结合起来就是,mmap可以代替read,而且更好?read函数至今存在,可能有其存在的理由。

2.2 Copy-on-Write机制

参考:COW奶牛!Copy On Write机制了解一下arrow-up-right

简单理解就是,多个进程起初共享一段内存(不同的进程有不同的虚拟地址空间,虚拟地址映射在相同的物理页,便共享同一段内存了)。当有个进程要对该内存进行写操作的时候,复制一份到其他物理页,该进程的虚拟地址空间的页表映射也修改,使得映射到新的物理页。

即,复制的操作推迟到需要写的时候才执行。详细见上面链接。

2.2.1 mmap函数MAP_PRIVATE参数

COW机制:复制内容到新内存 --> 修改页表映射,映射到新内存 --> 在新内存进行写操作。

image-20200628084053928

2.2.2 madvise函数

参考:/proc/self/arrow-up-right + C语言lseek()函数:移动文件的读写位置arrow-up-right + sizeof与strlen的区别arrow-up-right + [转]mmap和madvise的使用arrow-up-right

当使用madvise函数中的MADV_DONTNEED参数。进程会放弃已经复制的内存,修改页表映射重新执行原来的内存空间。

3. Dirty COW

  1. COW机制:复制内容到新内存 --> 修改页表映射,映射到新内存 --> 在新内存进行写操作。

  2. 当使用madvise函数中的MADV_DONTNEED参数。进程会放弃已经复制的内存,修改页表映射重新执行原来的内存空间。

  3. 所以,我们只需要,按照下面的顺序,便可以利用这里竞争条件漏洞(检查和执行分离)。

  4. 复制内容到新内存 --> 修改页表映射,映射到新内存 -->madvise,放弃已经复制的内存,修改页表映射重新执行原来的内存空间 --> 在内存进行写操作,便对只读文件进行了写操作。

image-20200628085734491

参考文章:Pthread线程简单使用arrow-up-right + linux C语言多线程编程,如何传入参数,如何获得返回值arrow-up-right + linux查看进程所有子进程和线程arrow-up-right

4. 结果

这个漏洞已经修复,我也偷懒没有去虚拟机安装一个旧版本的内核进行尝试。

可以参看:CVE-2016-5195漏洞分析与复现arrow-up-right

index

参考文章汇总

Race_Condition_Vulnerabilityarrow-up-right

C语言mmap()函数:建立内存映射arrow-up-right + man mmap + mmap和常规文件操作的区别arrow-up-right + Cache 和 Buffer 都是缓存,主要区别是什么?arrow-up-right

COW奶牛!Copy On Write机制了解一下arrow-up-right

/proc/self/arrow-up-right + C语言lseek()函数:移动文件的读写位置arrow-up-right + sizeof与strlen的区别arrow-up-right + [转]mmap和madvise的使用arrow-up-right

Pthread线程简单使用arrow-up-right + linux C语言多线程编程,如何传入参数,如何获得返回值arrow-up-right + linux查看进程所有子进程和线程arrow-up-right

CVE-2016-5195漏洞分析与复现arrow-up-right利用dirty cow(脏牛)漏洞的提权尝试 arrow-up-right

Last updated