首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >system() vs execve()

system() vs execve()
EN

Stack Overflow用户
提问于 2014-12-12 18:25:03
回答 3查看 19K关注 0票数 14

system()execve()都可以用来在程序中执行另一个命令。为什么在set-UID程序中,execve()是安全的,而system()是危险的?

EN

回答 3

Stack Overflow用户

发布于 2014-12-12 19:04:57

system将调用外壳程序(sh)来执行作为参数发送的命令。system的问题是因为外壳行为取决于运行命令的用户。下面是一个小示例:

创建文件test.c

代码语言:javascript
复制
#include <stdio.h>

int main(void) {
    if (system ("ls") != 0)
        printf("Error!");
    return 0;
}

然后:

代码语言:javascript
复制
$ 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的脚本:

代码语言:javascript
复制
$ cat > ls
#!/bin/sh

/bin/sh

$ chmod +x ls

现在:

代码语言:javascript
复制
$ 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行开头的脚本。

票数 20
EN

Stack Overflow用户

发布于 2014-12-12 18:40:34

system()execve()的工作方式不同。system()将始终调用shell,并且此shell将作为单独的进程执行命令(这就是在使用system()时可以在命令行中使用通配符和其他shell工具的原因)。

execve() (以及exec()系列中的其他函数)用直接产生的进程替换当前进程( execve()函数不会返回,除非出现故障)。实际上,system()实现应该使用一系列fork()execve()wait()调用来执行其功能。

当然,这两者都是危险的,这取决于进程拥有root权限时执行的是什么。然而,system()带来了一些额外的危险,因为它使用了额外的外壳“层”来打开房间安全漏洞,因为它调用了您的问题中的根外壳(即,进程具有suid位)。

票数 13
EN

Stack Overflow用户

发布于 2014-12-12 20:42:20

除了提到的system()的安全问题外,衍生的进程继承了主程序的环境。在使用suid时,这可能是非常有问题的,例如,当调用进程设置LD_LIBRARY_PATH-environment变量时。

使用exec()-family,调用程序可以在调用exec()之前将环境设置为被调用程序所需的环境(并且是安全的)。

当然,system()调用的shell本身也可能存在安全问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27461936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档