为什么应该避免使用 exec() 和 eval()?

2024-11-27 10:42:00
admin
原创
89
摘要:问题描述:我已在多个地方多次见到过这种情况,但从未找到令人满意的解释来解释为什么会出现这种情况。因此,希望这里能介绍一个。为什么我们(至少一般情况下)不应该使用exec()和eval()?编辑:我看到人们假设这个问题与 Web 服务器有关 - 但事实并非如此。我明白为什么传递未经清理的字符串exec可能会很糟...

问题描述:

我已在多个地方多次见到过这种情况,但从未找到令人满意的解释来解释为什么会出现这种情况。

因此,希望这里能介绍一个。为什么我们(至少一般情况下)不应该使用exec()eval()

编辑:我看到人们假设这个问题与 Web 服务器有关 - 但事实并非如此。我明白为什么传递未经清理的字符串exec可能会很糟糕。在非 Web 应用程序中这很糟糕吗?


解决方案 1:

通常有更清晰、更直接的方法来实现相同的效果。如果你构建一个复杂的字符串并将其传递给 exec,代码将很难理解,也很难测试。

示例:我编写了代码,读取字符串键和值并在对象中设置相应的字段。它看起来像这样:

for key, val in values:
    fieldName = valueToFieldName[key]
    fieldType = fieldNameToType[fieldName]
    if fieldType is int:
        s = 'object.%s = int(%s)' % (fieldName, fieldType) 
    #Many clauses like this...

exec(s)

对于简单情况来说,该代码还不算太糟糕,但随着新类型的出现,它变得越来越复杂。当出现错误时,它们总是在调用 exec 时触发,因此堆栈跟踪无法帮助我找到它们。最终,我改用了一个稍长、不太聪明的版本,明确设置了每个字段。

代码清晰度的第一条规则是,代码的每一行都应该易于理解,只需查看其附近的行即可。这就是为什么不鼓励使用 goto 和全局变量。exec 和 eval 很容易严重违反此规则。

解决方案 2:

当您需要 exec 和 eval 时,是的,您确实需要它们。

但是,这些函数(以及其他脚本语言中的类似构造)的大部分实际使用是完全不合适的,可以用其他更快、更安全、错误更少的更简单构造来代替。

可以通过适当的转义和过滤安全地使用 exec 和 eval。但是,直接使用 exec/eval 来解决问题的程序员(因为他们不了解该语言提供的其他功能)并不是能够正确进行处理的程序员;他们可能不了解字符串处理,只是盲目地连接子字符串,从而导致代码脆弱且不安全。

这就是字符串的诱惑。随意使用字符串段看起来很容易,并且会愚弄天真的程序员,让他们以为自己明白自己在做什么。但经验表明,在某些极端情况下(或不那么极端的情况下),结果几乎总是错误的,而且往往存在潜在的安全隐患。这就是为什么我们说 eval 是邪恶的。这就是为什么我们说 regex-for-HTML 是邪恶的。这就是为什么我们推动 SQL 参数化。是的,您可以通过手动字符串处理正确完成所有这些事情……但除非您已经理解我们为什么这么说,否则您很可能不会理解

解决方案 3:

除了安全性之外,eval它们exec通常由于其引起的复杂性而被标记为不受欢迎。当您看到一个eval调用时,您通常不知道它背后到底发生了什么,因为它对通常位于变量中的数据起作用。这使得代码更难阅读。

调用解释器的全部功能是一种重型武器,只应在非常棘手的情况下使用。然而,在大多数情况下,最好避免这样做,而应使用更简单的工具。

话虽如此,但像所有概括一样,要小心这一点。在某些情况下,exec 和 eval 可能很有价值。但你必须有充分的理由使用它们。请参阅这篇文章,了解一种可接受的用法。

解决方案 4:

eval()并且exec()会助长懒惰编程。更重要的是,它表明正在执行的代码可能不是在设计时编写的,因此未经测试。换句话说,你如何测试动态生成的代码?尤其是跨浏览器。

解决方案 5:

与此处大多数答案所说的相反,exec 实际上是在 Python 中构建超完整装饰器的方法的一部分,因为您可以完全复制有关装饰函数的所有内容,从而为文档等目的生成相同的签名。它是广泛使用的装饰器模块 ( http://pypi.python.org/pypi/decorator/ ) 功能的关键。exec/eval 必不可少的其他情况是构建任何类型的“解释型 Python”应用程序时,例如 Python 解析的模板语言(如 Mako 或 Jinja)。

因此,这些函数的存在并不代表应用程序或库存在“不安全”的问题。以简单的 javascripty 方式使用它们来评估传入的 JSON 或其他内容,是的,这非常不安全。但一如既往,这完全取决于您使用它的方式,而这些都是非常重要的函数。

解决方案 6:

在可能运行用户输入的环境中允许这些功能是一个安全问题,而且实际起作用的清理器很难编写。

解决方案 7:

我过去曾使用过eval()(现在仍然时不时地使用)在快速而粗糙的操作过程中处理数据。它是可用于完成工作的工具包的一部分,但绝不能用于您计划在生产中使用的任何东西,例如任何命令行工具或脚本,因为其他答案中提到了所有原因。

你不能相信你的用户会做正确的事情。在大多数情况下,他们会这样做,但你必须期望他们做所有你从未想过的事情,并发现所有你从未预料到的错误。这正是eval()从工具变成负担的地方。

一个完美的例子是使用 Django 构建QuerySet。传递给查询的参数接受关键字参数,如下所示:

results = Foo.objects.filter(whatever__contains='pizza')

如果您以编程方式分配参数,您可能会考虑执行如下操作:

results = eval("Foo.objects.filter(%s__%s=%s)" % (field, matcher, value))

但是总有一种不使用的更好方法eval(),即通过引用传递字典:

results = Foo.objects.filter( **{'%s__%s' % (field, matcher): value} ) 

通过这种方式,不仅性能更快,而且更安全、更符合 Python 风格。

这个故事的寓意是什么?

对于小任务、测试和真正临时的事情来说,使用eval()可以的,但对于永久使用来说却是不利的,因为几乎肯定总有更好的方法来完成它!

解决方案 8:

出于同样的原因,您不应该以 root 身份登录:这样很容易弄巧成拙。

解决方案 9:

请勿尝试在您的计算机上执行以下操作:

s = "import shutil; shutil.rmtree('/nonexisting')"
eval(s)

现在假设某人可以从 Web 应用程序控制 s。

解决方案 10:

原因#1:一个安全漏洞(即编程错误……我们不能声称这些错误可以避免)并且您刚刚授予用户访问服务器 shell 的权限。

解决方案 11:

在交互式解释器中尝试这个并看看会发生什么:

>>> import sys
>>> eval('{"name" : %s}' % ("sys.exit(1)"))

当然,这只是一个极端情况,但防止此类事情发生可能很棘手。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1043  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   41  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   35  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   32  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   34  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用