我正在研究 Android 漏洞利用Rage Against The Cage的实现。它背后的想法是,它会创建尽可能多的进程来RLIMIT_NPROC
获取shell UID,以便下次 Android 调试桥 (ADB) 守护进程尝试将其权限从root删除到shell时,调用setuid()
失败并继续执行以root身份(该错误已通过setuid()
在继续之前检查调用结果来修复)。
根据setrlimit()
文档,RLIMIT_NPROC
定义为:
可以为调用进程的真实用户 ID创建 [强调我的]的最大进程数(或者,更准确地说,在 Linux 上,线程数) 。遇到此限制时,fork(2) 将失败并显示错误 EAGAIN。对于具有 CAP_SYS_ADMIN 或 CAP_SYS_RESOURCE 功能的进程,不会强制执行此限制。
此外,这就是漏洞利用的实现方式:
/* generate many (zombie) shell-user processes so restarting
* adb's setuid() will fail.
* The whole thing is a bit racy, since when we kill adb
* there is one more process slot left which we need to
* fill before adb reaches setuid(). Thats why we fork-bomb
* in a seprate process.
*/
if (fork() == 0) { // 'true' for the child
close(pepe[0]);
for (;;) {
if ((p = fork()) == 0) {
exit(0); // child exits (???)
} else if (p < 0) {
if (new_pids) {
printf("\n[+] Forked %d childs.\n", pids);
new_pids = 0;
write(pepe[1], &c, 1);
close(pepe[1]);
}
} else {
++pids;
}
}
}
因此,RLIMIT_NPROC
它被定义为“可以创建的最大进程数”——创建,而不是“同时执行”——并且实现通过终止由第二个分叉创建的每个子进程来秒该定义。
首先,我无法理解如何限制每个 UID 创建的进程数量(我们必须不时重新启动机器以重置该计数,不是吗?)。其次,即使是对漏洞利用进行逆向工程的人,获得了与上面显示的实现等效的实现,也定义了RLIMIT_NPROC
不同的:
它[漏洞利用]利用了 RLIMIT_NPROC max,这是一个定义给定 UID 可以运行多少进程的值。
也就是说,RLIMIT_NPROC 实际是如何工作的?哪个定义更准确?