system()是否称为邪恶?

时间:2011-11-10 20:46:58

标签: c++ posix

我正在设计一个C ++应用程序,除其他外,它不时地执行一些脚本。该应用程序应该是高效的,最好是平台独立的。

但问题是:有没有理由不应该使用system()调用来启动脚本并使用例如POSIX设施?到目前为止,我所看到的关于此事的讨论通常归结为:

  1. system()不太灵活。 (好吧,我)
  2. 它无法控制正在执行的命令。 (对我很好,我只需要从脚本中返回值)
  3. 它不是独立于平台的。 (现在,这将是一个问题。我真的很想看到一个在不同平台上表现不同的例子)
  4. 这是一个安全问题。 (同样,这也是一个问题。有人可以提供system()潜在安全问题的示例吗?)
  5. 还有其他问题吗?

6 个答案:

答案 0 :(得分:5)

  

3)它不是平台独立的(现在,这将是一个问题。我真的很想看到一个例子,它在不同的平台上表现不同)

嗯,例如,system("ls")可能在Windows中失败,因为没有 ls 命令。

  

4)这是一个安全问题。 (同样,这将是一个问题。有人可以提供system()潜在安全问题的示例吗?)

如果传递给system的参数来自用户输入,并且未经过适当验证,则可以使用原始执行程序的权限级别执行不需要的操作。如果它的静态内容,很容易在可执行映像中找到它并修改它以做坏事。

答案 1 :(得分:3)

(3)如果你只想要一个反例,例如grep在Solaris vs Linux上的表现与其他方面不同。

(4)您的程序的权限由其衍生的程序继承。如果您的应用程序曾作为特权用户运行,那么所有人必须做的就是将自己的程序与您所发现的东西的名称放在一起,然后可以执行任意代码(这意味着您永远不应该运行使用{{{ 1}}作为root或setuid root)。

(5)从长远来看,使用posix工具可能更为合理,因为在程序运行的任何地方都不需要依赖一组特定的外部脚本或二进制文件。

答案 2 :(得分:1)

我维护一个由几个独立的可执行文件组成的系统。在这种情况下,我可以控制所有支持平台上的权限,名称,调用约定和安全性。在这种情况下,system()工作正常。应用程序通过RDBMS进行通信。

再次,正如其他人已经注意到“细节中的魔鬼”。

答案 3 :(得分:1)

关于安全问题,关于(4)的经典示例是以下场景:假设提示用户将某些目录名称备份到std::string dirname;然后你将一些备份目录名称计算到std::string backup并执行

system((std::string{"cp -a "} + dirname + " " + backup).c_str())

现在想想如果恶意用户输入foo bar; rm -rf $HOME; lsdirnamebackup/vol/backup_2015_fev/会发生什么。 system命令将执行

cp -a  foo bar; rm -rf $HOME; ls /vol/backup_2015_fev/

这不是您所期望的(将删除所有用户的$HOME!)。这是code injection的示例,当使用system时,您应确保它永远不会发生(例如,通过清理和/或转义每个用户输入相关的字符串)

此外,PATH可能不是您认为的那样(例如,从/tmp/开始,恶意用户在ln -s /bin/rm /tmp/cp运行之前已经完成system。< / p>

答案 4 :(得分:0)

我在Windows和Linux下的CGI C ++应用程序中也使用了system()调用。

我遇到的一个问题是使用system()时没有适当的访问权限来执行我与Web用户的skript。

使用CreateProcess()方法时,我不再遇到这个问题了。

答案 5 :(得分:0)

无论您要执行什么命令,都将其存储在文件c.txt中。将该文件传递到execl(),如下所示。

fd = open("c.txt", O_CREAT | O_RDWR, 00777);
write(fd,arr,sizeof(arr));
if(fork() == 0)
{
    execl("/bin/sh", "sh", "-c","sh c.txt", (char *) 0);
}