我偶然发现了使用suid
可执行文件访问系统文件的问题。
我写了这篇简短的POC:
#include <unistd.h>
#include <stdio.h>
int main()
{
if (access("/etc/shadow", W_OK) == 0)
printf("shadow writable!\n");
else
printf("shadow not writable\n");
return 0;
}
然后我编译并用chown root:root
和chmod u+s
(由root运行)给它带来了suid
这是生成的可执行文件
-rwsrwxr-x 1 root root 4847 Apr 14 08:40 a.out
目标文件具有这些权利
-rw------- 1 root root 1836 Oct 8 2014 /etc/shadow
当我运行程序时,它给出了这个输出:
[d.berra@srvr ~]$ ./a.out
shadow not writable
为什么会这样?我的意思是......我正在root
访问该文件,root
CAN 在此文件上写字!
注意:selinux
已停用
想法?
答案 0 :(得分:3)
来自access
:
使用调用进程的真实 UID和GID完成检查,而不是在文件上实际尝试操作(例如,open(2))时完成的有效ID。这允许set-user-ID程序轻松确定调用用户的权限。
因此,您可以成功打开此文件进行写入,因为您的有效UID和文件系统UID现在为0,但访问仍会返回错误。
正如@nos所说,您忘了将可执行文件所有者更改为root
:
$ sudo chown root:root ./a.out
但即使你这样做,由于access
行为,你仍然会“不可写”:
$ ls -l ./a.out
-rwsr-xr-x 1 root root 12651 Apr 14 09:53 ./a.out
$ ./a.out
shadow not writable
答案 1 :(得分:3)
您设置suid位,这意味着可执行文件将以拥有可执行文件的用户身份运行。可执行文件将以d.berra
运行,无法写入/etc/shadow
。
如果您希望可执行文件以root身份运行而不管运行它的用户是什么,除了设置suid位之外,可执行文件应该由root拥有。
答案 2 :(得分:1)
试试这个:
#include <unistd.h>
#include <stdio.h>
int main()
{
setuid(0);
if (access("/etc/shadow", W_OK) == 0)
printf("shadow writable!\n");
else
printf("shadow not writable\n");
return 0;
}
它将用户ID设置为root以便能够访问该文件。 setuid(0)仅在有效用户ID也为0的情况下有效。