Set-UID能力泄漏攻击

Set-UID能力泄漏攻击

我有一个C程序来演示capability leak有关 set-uid 的攻击。

// cap_leak.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

void main()
{  
    int fd;  char *v[2];  
    /* Assume that /etc/zzz is an important system file, and it is owned by root with permission 0644. Before running this program, you should create the file /etc/zzz first. */  

    fd = open("/etc/zzz", O_RDWR | O_APPEND);

    // Print out the file descriptor value  
    printf("fd is %d\n", fd);    
    if (fd == -1) 
    {     
        printf("Cannot open /etc/zzz\n");     
        exit(0);  
    }  
    // Permanently disable the privilege by making the  
    // effective uid the same as the real uid  
    setuid(getuid()); 
    printf("Real user id is %d\n", getuid());    
    printf("Effective user id is %d\n", geteuid());    

    // Execute /bin/sh  
    v[0] = "/bin/sh"; v[1] = 0;  
    execve(v[0], v, 0);        
}

原来,cat /etc/zzz给出:

this is a very important file

现在我编译这个程序:

gcc -o cap_leak cap_leak.c

将所有者更改为 root 并打开 setuid 位:

sudo chown root cap_root
sudo chmod 4755 cap_root

现在,当我从普通用户运行该程序时,我会收到 shell 提示:

fd is 3
Real user id is 1000
Effective user id is 1000
$whoami
$seed
$echo bbbbbb >&3
$cat /etc/zzz
$this is a very important file
 bbbbbb

最后一次写入fd = 3ie/etc/zzz是成功的,尽管在打开文件后setuid()调用该函数,该函数基本上将真实、有效和保存的 uid 设置为原始 uid。我的问题是,为什么最后一次写入成功,即使它是在之后执行的setuid()并且为了防止这种情况下的能力泄漏,应该setuid()将其放置在哪里以及为什么?

答案1

没有其他地方应该放置setuid(),也不应该让文件保持打开状态以供写入。

原因是打开文件时会检查权限,而不是每次write()调用时都会检查权限。

如果非特权 shell 不应该写入该文件,则没有理由让该文件保持打开状态并具有写访问权限。

相关内容