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