ALL system()是否在c ++中调用安全风险?

时间:2018-01-03 01:19:35

标签: c++ security c++11 operating-system

此(Are system() calls evil?)帖子中的帖子说:

  

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

但是system("PAUSE")system("CLS")是操作系统的外壳,所以如果黑客只能封装到硬盘驱动器上的特定安全位置,黑客怎么可能介入?

在调用系统之前使用fflush或_flushall显式刷新还是关闭任何流消除所有风险?

2 个答案:

答案 0 :(得分:2)

  

系统函数将命令传递给命令解释器,命令解释器将字符串作为操作系统命令执行。系统使用COMSPEC和PATH环境变量来定位命令解释程序文件CMD.exe。如果command为NULL,则该函数仅检查命令解释器是否存在。

     

在调用系统之前,必须使用fflush或_flushall明确刷新 - 或关闭任何流。

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/system-wsystem

如果有任何疑问,这是MS实施的实际片段(非常简单明了):

// omitted for brevity
argv[1] = _T("/c");
argv[2] = (_TSCHAR *) command;
argv[3] = NULL;

/* If there is a COMSPEC defined, try spawning the shell */

/* Do not try to spawn the null string */
if (argv[0])
{
     // calls spawnve on value of COMSPEC vairable, if present
     // omitted for brevity
}

/* No COMSPEC so set argv[0] to what COMSPEC should be. */
argv[0] = _T("cmd.exe");

/* Let the _spawnvpe routine do the path search and spawn. */

retval = (int)_tspawnvpe(_P_WAIT,argv[0],argv,NULL);
// clean-up part omitted

至于对_tspawnvpe实际可能做的事情的关注,答案是:没有什么神奇之处。 spawnvpe和朋友的确切调用顺序如下(因为任何拥有许可版本的MSVC的人都可以通过检查spanwnvpe.c源文件轻松学习):

  1. 对参数进行一些健全性检查
  2. 尝试在传递的文件名上调用_tspawnve。如果文件名表示可执行文件的绝对路径或相对于当前工作目录的有效路径,则spawnve将成功。没有进一步的检查 - 所以是的,如果当前目录中存在名为cmd.exe的文件,它将在system()调用的讨论的上下文中首先被调用。
  3. 在循环中:使用`_getpath()获取下一个路径元素
    1. 将文件名附加到路径元素
    2. 将生成的路径传递给spwanvpe,检查是否成功
  4. 就是这样。没有特别的技巧/检查。

答案 1 :(得分:1)

原始问题引用POSIX而非Windows。这里没有COMSPEC(有SHELLsystem()故意不使用它);但/bin/sh完全是完全脆弱的。

假设/ opt / vuln / program system("/bin/ls");看起来完全无害,对吧?都能跟得上!

$ PATH=. IFS='/ ' /opt/vuln/program

这将在当前目录中运行名为bin的程序。哎呀。防范这种事情是如此困难,应该留给极端的专家,比如撰写sudo的人。消毒环境非常困难。

所以你可能会想到system() api是什么。我实际上并不知道它是为什么被创建的,但是如果你想做一个像ftp这样的功能,那么!在shell中本地执行!命令你可以做... else if (terminalline[0] == '!') system(terminalline+1); else ...因为它是'无论如何,这将是完全不安全的,没有必要使其安全。当然,一个真正现代的用例不会这样做,因为system()并没有看$SHELL但是很好。