我用c语言封装了一条cat /etc/shadow的命令,设置程序的的suid位并把它的属主设为root,为什么以普通用户执行时,还是不能访问/etc/shadow?难道是exec执行新程序时不继承suid属性吗?
// encapsulation.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(){
printf("uid is %d\n", getuid());
printf("euid is %d\n", geteuid());
execlp("/bin/sh", "sh", "-c","echo $UID $EUID;/bin/cat /etc/shadow", (char*)NULL);
return 0;
}
➜ test gcc encapsulation.c -o encapsulation
➜ test ./encapsulation
uid is 1000
euid is 1000
/bin/cat: /etc/shadow: Permission denied
➜ test sudo chown root:root encapsulation
[sudo] password for inovker:
➜ test ./encapsulation
uid is 1000
euid is 1000
/bin/cat: /etc/shadow: Permission denied
➜ test sudo chmod u+s encapsulation
➜ test ./encapsulation
uid is 1000
euid is 0
/bin/cat: /etc/shadow: Permission denied
➜ test sudo ./encapsulation
uid is 0
euid is 0
root:!:17655:0:99999:7:::
daemon:*:17647:0:99999:7:::
bin:*:17647:0:99999:7:::
sys:*:17647:0:99999:7:::
sync:*:17647:0:99999:7:::
games:*:17647:0:99999:7:::
man:*:17647:0:99999:7:::
...
出于安全原因,bash是会检查euid和uid的,发现不一样就会切换回去,所以会出现Permission denied。
具体实现可以看bash代码里的
uidget
和disable_priv_mode
。解决方法是用bash的
-p
,打开特权模式。或者直接不用bash,直接调用cat。