安全地执行来自 Python 中用户输入的脚本

问题描述 投票:0回答:1

我正在 Python 中寻找一种安全机制来执行来自用户的潜在不安全脚本代码。

代码示例:

def public(v):
    print('Allowed to trigger this with '+v)
    
def secret():
    print('Not allowed to trigger this')
    

unsafe_user_code = '''
def user_function(a):
    if 'o' in a:
        public('parameter')

a = 'hello'
user_function(a)
'''

run_code(unsafe_user_code, allowed=['public'])

这可以通过

exec()
轻松实现,但据我了解,在 Python 中无法安全地使用
exec()

这是我的要求:

  1. 脚本的语法理想情况下应类似于 Python(但也可以类似于 JavaScript)
  2. 脚本中需要提供标准机制,例如字符串操作、if/else/while 以及自己的变量和函数的定义
  3. 脚本应该只能执行某些功能(在示例中,只允许
    public()
  4. 我只想依赖基于 Python 的实现/库,因为我不想依赖 Python 外部软件
  5. 它不应该引入安全风险

到目前为止我发现的唯一方法是使用解析库,我必须自己定义所有内容(例如这个:https://github.com/lark-parser/lark)。

有没有更好的方法来实现这样的目标?

谢谢!

python parsing security exec
1个回答
1
投票

回答

如果您想复制,这里是完整的 python 文件:

def run_code(code_to_run: str, context: dict):

    code = compile(code_to_run, "", "exec")
    exec(code, context)

    return

具有以下用法:

variables = {"variable_a": "A", "variable_b": "B", "variable_c": "C"}

run_code(
    """
# We can work with the variables here
all_variables = [variable_a, variable_b, variable_c]
joined = ",".join(all_variables)
print("Joined:", joined)
combined = variable_a + variable_b + variable_c
print("Combined:", combined)
""",
    variables,
)

它会打印到终端:

Joined: A,B,C
Combined: ABC

说明

我认为你不需要解析库。 您可以使用 python 的内置函数之一,称为 compile()

你可以这样编译代码:

    text_to_compile = "print('hello world')"
    code = compile(
      text_to_compile, # text to compile
      'file_name', # file name
      'exec' # compile mode
    )

有关编译模式的更多信息

然后使用内置的 exec 函数运行它:

    exec(code) # prints 'hello world' in the terminal

如果您想限制其对变量的访问,您可以定义其

globals
locals
并作为第二个和第三个参数传递:

global_variables = { "cool":"cool value" }
local_variables = {"more_cool": "cool value"}
exec(
    code,
    global_variables,
    local_variables
)

如果你给它这个代码:

print("GLOBALS:", list(globals().keys()))
print("LOCALS:", list(locals().keys()))

print("cool:", cool)
print("more_cool:", more_cool)

它输出:

GLOBALS: ['cool', '__builtins__']
LOCALS: ['more_cool']
cool: cool value
more_cool: cool value
© www.soinside.com 2019 - 2024. All rights reserved.