1

我正在研究 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 实际是如何工作的?哪个定义更准确?

4

1 回答 1

1

限制确实是当前进程的数量,而不是自系统启动以来创建的进程总数。

漏洞利用代码如何工作的关键是僵尸进程。即使子进程调用了 exit(),它们仍然被操作系统保留并计入限制,直到父进程放弃它们或调用 wait()。在这种情况下,父级不会这样做,因此它们会一直徘徊,直到父级本身退出。

于 2016-07-05T21:33:09.350 回答