禁用C和Pascal中的system()和exec()函数
Disable system() and exec() function in C and Pascal
是否有任何方法禁用system()
和exec()
功能在C/c++和Pascal,通过使用任何编译器参数或修改头/单元文件?(这是一台Windows)
我已经尝试使用-Dsystem=NONEXIST
为gcc和g++,但#include <cstdio>
导致编译错误。
#undef system
来绕过防御,所以我试着在stdlib.h中注释掉system
函数行,但这也不起作用。
EDIT2(注释):它是一个系统,用户提交他们的程序,服务器用不同的输入数据编译并运行它,然后将程序输出与预先计算的标准输出进行比较,看程序是否正确。现在一些用户发送类似system("shutdown -s -t 0");
的代码来关闭服务器。
服务器运行Windows系统,所以我没有任何chroot环境。此外,服务器应用程序是闭源的,所以我不能做什么来控制用户提交的程序是如何执行的。我能做的是修改编译器命令行参数和修改头文件。
好吧,你可以试试:
#define system DontEvenThinkAboutUsingThisFunction
#define exec OrThisOneYouClown
在头文件中,但我很确定任何一个称职的代码猴子都可以绕过这样的"保护"。
我很想了解为什么你认为这是必要的(如果我们更好地理解这个问题,可能会有更好的解决方案)。
唯一想到的是你想提供一些类似于Euler项目的在线编译器/运行器。如果是这种情况,那么您可以在代码中搜索字符串system<whitespace>(
作为选项,但即使这样,有决心的一方也可以:
#define InoccuousFunction system
来绕过你的防御。
如果是的情况,您可能想要考虑使用chroot
之类的东西,这样没有人甚至可以获得访问到任何危险的二进制文件,如shutdown
(而且那个特定的野兽无论如何都不应该由普通用户运行)-换句话说,限制他们的环境,使只有他们甚至可以看到gcc
和它的同类。
你需要做适当的沙箱,因为即使你以某种方式阻止他们运行外部程序,他们仍然可能做一些危险的事情,比如覆盖文件或打开套接字连接到他们自己的盒子,通过你的宝贵信息的内容发送。
一种可能性是创建您自己版本的这些函数,并将它们链接到您在服务器上编译/链接的每个程序中。如果在对象中找到该符号,它将优先。
确保你得到了它们;)
使用尽可能少的权限的用户运行程序会更好。这样你就不用担心他们会删除/访问系统文件,关闭系统等等。
EDIT:当然,根据我的逻辑,用户也可以提供他们自己版本的函数,它可以动态加载库&符号查找查找原始函数。你只需要对它进行沙盒处理。
对于单类环境,有Geordi,它使用操作系统的大量帮助来沙箱化要执行的代码。
基本上你想在一个非常受限的环境中运行代码;Linux提供了一个特殊的进程标志,用于禁用任何系统调用,这些系统调用将允许访问进程在设置该标志时没有的资源(即,它禁止打开新文件,但任何已经打开的文件都可以正常访问)。
我认为Windows应该有类似的机制。
不是真的(因为调用一些会调用system
本身的库函数的技巧,或者因为生成进程的功能可以只用fork
&execve
系统调用,仍然可用…)。
但是为什么要问呢?
你永远不能(正如你所发现的)依赖用户输入是安全的。system
和execXX
不太可能是您唯一的问题。
这意味着您有以下选项:
- 在某种
chroot
版本的监狱中运行程序(不确定如何在windows上这样做) - 编译前扫描代码,确保没有"非法"函数。
- 编译后扫描可执行二进制文件,确保它没有使用任何"禁止"的库函数。
- 阻止链接器链接到任何外部库,包括unix上的标准C库(libc)。然后,您可以创建自己的"libc",它显式地允许某些功能。
Number 3在unix上可以使用像readelf或objdump这样的工具来检查链接的符号。这也可以使用二进制文件描述符库来完成。
第4条需要修改编译器标志,但可能是上面列出的选项中最安全的。
你可以这样写
#include<stdlib.h>
#include<unistd.h>
#define system <stdlib.h>
#define exec <unistd.h>
在这种情况下,即使用户想要交换宏值,他们也不能。如果它们试图像这样交换宏值
#define <stdlib.h> system
#define <unistd.h> exec
不能,因为C不允许在宏中使用这种类型的名字。即使它们以某种方式交换了这些值,那么我们已经包含了那些将创建编译时错误的头文件。
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- Python 的 exec() 函数的 C++ 版本
- PHP 网站在传递图像作为参数时未运行 exec 函数
- 将 PHP 中的 $_POST 变量传递给由 exec() 函数运行的C++程序
- 如何在 exec 循环停止后正确使用 QSharedPointer 的析构函数<QObject>?
- 使用CreateProcess尽可能使用单个命令参数调用exec*函数
- 在参数中传递给 exec*() 函数系列的内存会发生什么情况
- 如何在linux中使用c或c++在不使用system()或exec()函数的情况下调用像pwd或ls-l这样的系统函数
- 如何在c++中对exec()进行析构函数友好的调用
- 禁用C和Pascal中的system()和exec()函数
- c++通过exec函数杀死子进程,但不杀死父进程和正常运行时间
- 如何在c++中实现Python函数exec()
- 使QDialog显示show或exec函数