system()和execve()都可以用来在程序中执行另一个命令。为什么在set-UID程序中,execve()是安全的,而system()是危险的?
发布于 2014-12-12 19:04:57
system将调用外壳程序(sh)来执行作为参数发送的命令。system的问题是因为外壳行为取决于运行命令的用户。下面是一个小示例:
创建文件test.c
#include <stdio.h>
int main(void) {
if (system ("ls") != 0)
printf("Error!");
return 0;
}然后:
$ gcc test.c -o test
$ sudo chown root:root test
$ sudo chmod +s test
$ ls -l test
-rwsr-sr-x 1 root root 6900 Dec 12 17:53 test在当前目录中创建一个名为ls的脚本:
$ cat > ls
#!/bin/sh
/bin/sh
$ chmod +x ls现在:
$ PATH=. ./test
# /usr/bin/id
uid=1000(cuonglm) gid=1000(cuonglm) euid=0(root) egid=0(root) groups=0(root),
24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),105(scanner),
110(bluetooth),111(netdev),999(docker),1000(cuonglm)
# /usr/bin/whoami
root哦,您得到了一个具有root权限的shell。
execve不调用外壳。它执行作为第一个参数传递给它的程序。该程序必须是二进制可执行文件或以shebang行开头的脚本。
发布于 2014-12-12 18:40:34
system()和execve()的工作方式不同。system()将始终调用shell,并且此shell将作为单独的进程执行命令(这就是在使用system()时可以在命令行中使用通配符和其他shell工具的原因)。
execve() (以及exec()系列中的其他函数)用直接产生的进程替换当前进程( execve()函数不会返回,除非出现故障)。实际上,system()实现应该使用一系列fork()、execve()和wait()调用来执行其功能。
当然,这两者都是危险的,这取决于进程拥有root权限时执行的是什么。然而,system()带来了一些额外的危险,因为它使用了额外的外壳“层”来打开房间安全漏洞,因为它调用了您的问题中的根外壳(即,进程具有suid位)。
发布于 2014-12-12 20:42:20
除了提到的system()的安全问题外,衍生的进程继承了主程序的环境。在使用suid时,这可能是非常有问题的,例如,当调用进程设置LD_LIBRARY_PATH-environment变量时。
使用exec()-family,调用程序可以在调用exec()之前将环境设置为被调用程序所需的环境(并且是安全的)。
当然,system()调用的shell本身也可能存在安全问题。
https://stackoverflow.com/questions/27461936
复制相似问题