这是评估的有效用例吗?我怎样才能避免安全风险?

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

我使用 Python 3.11 引入的 switch 语句解决了这个 Hackerrank 挑战。我使用

eval
动态执行输入中给出的命令。

但是,我知道动态执行代码可能会导致安全风险。我已经读过关于该主题的旧讨论:为什么使用“eval”是一种不好的做法?所以我想知道是否有其他方法来使用它,或者这可能是 eval 的有效用例。

我真的不喜欢诸如“始终避免这种情况”之类的陈述,因为我们有使用它的命令,如果我们应该始终避免它,那么为什么不直接删除它们呢?对我来说,最好了解风险并知道如何避免它们,并在没有有效用例时给出有效用例和替代方案的示例。

对我来说,下面的代码是一个有效的用例,但如果您认为存在真正的风险,我将不胜感激其他意见。我主要是 Ruby 开发人员,所以我仍然不知道 Python 的所有细微差别。

def call_fun(i_lst):
    args_num = len(i_lst)
    
     
    match args_num:
        case 1:
            if i_lst[0] == "print":
                eval(i_lst[0] + "(o_list)")
            else:
                eval("o_list.{}()".format(*i_lst))
        case 2:
            eval("o_list.{}({})".format(*i_lst))
        case 3:
            eval("o_list.{}({},{})".format(*i_lst))

if __name__ == '__main__':
    N = int(input())
    o_list = []
    
    for x in range(N):
        command = input().split()
        call_fun(command)

我知道我将收到与列表方法(追加、插入、排序等)和打印语句匹配的字符串。这些方法及其参数是我的输入列表 (i_lst)。

我认为这是 eval 的有效用例,因为 eval 只能执行单个表达式,并且我附加到列表命令,因此如果输入中有意包含恶意代码,则会引发语法错误。我在我的翻译中尝试过这个案例,以确保:

a_lst = ["append", "5); print('Unsafe'"]

所以,如果我可以引入恶意代码,我就可以执行

append
,然后执行任何恶意代码。但是,当我使用 eval 运行它时,它给出了以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in call_fun
  File "<string>", line 1
    o_lst.append(5); print('Unsafe')
                   ^
SyntaxError: invalid syntax

因此,我倾向于认为这是一个安全的实现。

我阅读了使用全局变量和局部变量的建议通过 eval 限制安全风险,但不确定如何实现,如果在这种情况下,那就太好了。

是否有任何其他情况可能存在我所遗漏的安全风险,因此最好避免“评估”?或者您也认为这是一个安全有效的用例?

python python-3.x security eval
1个回答
1
投票

这是评估的有效用例吗

一般来说,不会。假装它不存在,您最终会得到更清洁、更安全的解决方案:

def call_fun(cmd):
    match cmd:
        case ["print"]:
            print(o_list)
        case ["sort"]:
            o_list.sort()
        case ["pop"]:
            o_list.pop()
        case ["reverse"]:
            o_list.reverse()
        case ["remove", value]:
            o_list.remove(int(value))
        case ["append", value]:
            o_list.append(int(value))
        case ["insert", index, value]:
            o_list.insert(int(index), int(value))

或者如果你坚持的话,

def call_fun(cmd):
    match cmd:
        case ["print"]:
            print(o_list)
        case [("sort" | "pop" | "reverse" | "remove" | "append" | "insert") as method, *args]:
            getattr(o_list, method)(*map(int, args))

是的,如果卡中存在恶意输入,您的代码很容易受到攻击 – 可以执行任意代码(网上有很多关于如何利用

eval
的示例),但也仅适用于以下情况:

append open("/etc/passwd").read()
© www.soinside.com 2019 - 2024. All rights reserved.