在 c++ 中,所有 system() 调用都存在安全风险吗?
Are ALL system() calls a security risk in c++?
这个(system()称之为邪恶吗?)线程中的帖子说:
程序的权限由其生成的程序继承。如果你的应用程序曾经以特权用户的身份运行,那么人们所要做的就是用你掏出的东西的名字来放置他们自己的程序,然后可以执行任意代码(这意味着你永远不应该运行使用系统作为root或setuid根的程序)。
但是system("PAUSE")
和system("CLS")
外壳到操作系统,那么如果黑客只外壳到硬盘驱动器上的特定安全位置,它怎么可能干预呢?
显式刷新(通过使用 fflush 或 _flushall)或在调用系统之前关闭任何流是否可以消除所有风险?
最初的问题引用的是POSIX而不是Windows。这里没有COMSPEC
(有SHELL
但system()
故意不使用它);然而,/bin/sh
完全、完全脆弱。
假设/opt/vuln/program 看起来完全无害system("/bin/ls");
,对吧?不!
$ PATH=. IFS='/ ' /opt/vuln/program
这将在当前目录中运行名为bin
的程序。哎呀。防御这种事情是如此困难,应该留给极端专家,比如写sudo
的人。消毒环境非常困难。
所以你可能会想system()
api 有什么用。我实际上不知道为什么创建它,但是如果您想做一个像ftp
这样的功能,其中 !command 在 shell 中本地执行,您可以... else if (terminalline[0] == '!') system(terminalline+1); else ...
由于无论如何它都是完全不安全的,因此没有必要使其安全。当然,一个真正现代的用例不会这样做,因为system()
不看$SHELL
但哦,好吧。
system 函数将命令传递给命令解释器,命令解释器将字符串作为操作系统命令执行。 系统使用 COMSPEC 和 PATH 环境变量来定位命令解释器文件 CMD.exe。如果命令为 NULL,则该函数仅检查命令解释器是否存在。
在调用系统之前,必须显式刷新(使用 fflush 或 _flushall)或关闭任何流。
https://learn.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
源文件轻松学习):
- 对参数进行一些健全性检查
- 尝试对传递的文件名调用
_tspawnve
。 如果文件名表示可执行文件的绝对路径或相对于当前工作目录的有效路径,则spawnve
成功。没有进行进一步的检查 - 所以是的,如果当前目录中存在名为cmd.exe
的文件,它将首先在讨论system()
调用的上下文中调用。 - 在循环中:使用 '_getpath() 获取下一个路径元素
- 将文件名追加到 path 元素
- 将结果路径传递给
spwanvpe
,检查是否成功
就是这样。不涉及特殊技巧/检查。
- 从不同线程使用int64的不同字节安全吗
- C++模板来检查友元函数的存在
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 虚拟决赛作为安全
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 既然存在危险,为什么项目要使用-I include开关
- 我们可以访问一个不存在的联盟的成员吗
- C++:对不存在的命名空间使用命名空间指令
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- C++quit()函数中可能存在作用域问题
- C++擦除(如果存在)
- 在 c++ 中,所有 system() 调用都存在安全风险吗?
- 可以归类为病毒的程序可能存在安全缺陷
- stl或boost中是否存在用于线程间通信的线程安全结构,其行为类似于队列
- 此 strncpy 存在哪些安全问题
- 如果存在仅推送线程和仅弹出线程,那么C++std::队列安全吗
- Boost smart_ptr非线程安全宏,它真的存在吗?
- 从lambda的内部框架修改via闭包中的变量安全吗?lambda是从一个不再存在的函数创建的
- 如果异常保存在std::exception_ptr中,那么在catch语句之外使用异常是否安全?