Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在嵌入式Python中禁用内置模块导入_Python_C++_Python 3.x_Python Embedding - Fatal编程技术网

在嵌入式Python中禁用内置模块导入

在嵌入式Python中禁用内置模块导入,python,c++,python-3.x,python-embedding,Python,C++,Python 3.x,Python Embedding,我正在我的应用程序中嵌入Python3.6,我想在脚本中禁用import命令,以防止用户导入任何Python内置库。我只想使用语言本身和我自己的C++定义的模块。 Py_SetProgramName(L“示例”); Py_初始化(); PyObject*mainModule=PyImport\u AddModule(“\uuuu main\uuuu”); PyObject*globals=PyModule_GetDict(主模块); //这应该行得通 std::string script1=“打

我正在我的应用程序中嵌入Python3.6,我想在脚本中禁用import命令,以防止用户导入任何Python内置库。我只想使用语言本身和我自己的C++定义的模块。
Py_SetProgramName(L“示例”);
Py_初始化();
PyObject*mainModule=PyImport\u AddModule(“\uuuu main\uuuu”);
PyObject*globals=PyModule_GetDict(主模块);
//这应该行得通
std::string script1=“打印('example')”;
PyRun_字符串(script1.c_str(),Py_file_输入,globals,nullptr);
//这不应该奏效
std::string script2=“导入随机\n”
“打印(random.randint(1,10))\n”;
PyRun_字符串(script2.c_str(),Py_file_输入,globals,nullptr);
Py_();

您知道实现这一点的方法吗?

Python长期以来不可能创建一个安全的沙箱(作为起点,如果您愿意,可以跳入旧沙箱)。以下是我认为你最好的两种选择。 预先扫描代码 在执行任何操作之前,先扫描代码。您可以在Python中使用,然后遍历树,也可以使用更简单的文本搜索。这可能适用于您的场景,因为您有限制的用例-它不能推广到真正的任意代码

在您的案例中,您需要的是任何
import
语句(简单),以及任何未“批准”的顶级变量(例如,在
a.b.c
中,您关心
a
,对于给定的
a
),可能是
a.b
)。这将使您能够在运行任何不干净的代码之前失败

这里的挑战是,即使是经过三层模糊处理的代码也会绕过您的检查。例如,这里有一些方法可以导入给定的其他模块或全局模块,而
import
的基本扫描无法找到这些模块或全局模块。您可能希望限制直接访问
\uuuuuuuuuuuuuuuuuuuuuuu
全局
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在AST中,这些将不可避免地显示为顶级变量读取或属性访问

getattr(__builtins__, '__imp'+'ort__')('other_module')

globals()['__imp'+'ort__']('other_module')

module.__loader__.__class__(
    "other_module",
    module.__loader__.path + '/../other_module.py'
).load_module()
(我希望不用说,这是一个不可能的挑战,以及为什么这种沙箱方法从未完全成功。但它可能足够好,取决于您的特定威胁模型。)

运行时审计

如果您有能力编译自己的Python运行时,您可以考虑使用(当前草案)挂钩。(免责声明:我是本PEP的作者。)有针对最新和最新版本的实现草案

本质上,这将允许您为Python中的一系列事件添加挂钩,并确定如何响应。例如,您可以侦听所有
import
事件,并根据要导入的模块确定在运行时是否允许这些事件,或者侦听
compile
事件以管理所有运行时编译。可以从Python代码(使用
sys.addaudithook
)或C代码(使用
PySys\u addaudithook
)执行此操作

repo中的文件是从C进行审计的一个相当彻底的例子,而从Python进行审计看起来更像这样(摘自关于这个PEP):


这种方法的缺点是您需要构建和分发自己的Python版本,而不是依赖于系统安装。但是,一般来说,如果应用程序依赖于嵌入,这是一个好主意,因为这意味着您不必强迫用户进入特定的系统配置。

一瞥:删除
eval
exec
sys
os
也一样。当然,我想禁用除我自己的模块之外的所有功能。请注意,您可以通过覆盖
内置项来控制所有
import
语句。\uuuuu导入\uuuuu
属性和自定义函数。(这并不能使Python对恶意用户具有健壮性,但可以在您的简单示例中使用。)非常详细的回答,谢谢,我认为这是一个非常好的起点。一个问题:为什么我必须检查顶级变量?在这种情况下,什么样的变量会导致麻烦?@kovacsv我的评论开始变长,因此我在答案中添加了内容。非常感谢,现在我明白了问题的复杂性。
import sys

def prevent_bitly(event, args):
    if event == 'urllib.Request' and '://bit.ly/' in args[0]:
        print(f'WARNING: urlopen({args[0]}) blocked')
        raise RuntimeError('access to bit.ly is not allowed')

sys.addaudithook(prevent_bitly)