可以将`setattr`(和`getattr`)的使用视为不良做法吗?

时间:2012-12-20 23:47:48

标签: python getattr setattr

setattrgetattr类似于我的编程风格(主要是科学的东西,我对python的了解是自我告诉)。

考虑到execeval继承了潜在的危险,因为在某些情况下它们可能导致安全问题,我想知道setattr是否认为相同的参数是有效的。 (关于getattr我发现this question包含了一些信息 - 尽管论证并不十分令人信服。)

据我所知,setattr可以使用而不用担心太多,但说实话我不相信我的python知识足以确定,如果我错了我想试试并摆脱使用setattr的习惯。

非常感谢任何输入!

1 个答案:

答案 0 :(得分:10)

首先,它绝对可以使现有的安全漏洞更容易。

例如,假设你有代码执行execeval,SQL查询或通过字符串格式化构建的URL等等。让我们说你正在传递,比如{{1} }或过滤的locals()到格式化命令或__dict__上下文或其他任何内容。使用eval可以明显加宽安全漏洞,使我更容易找到攻击代码的方法,因为您无法再确定将要传递给这些函数的内容。

但是,如果你不做任何其他不安全的事情怎么办? setattr安全吗?

没有那么糟糕,但它仍然不安全。如果我可以影响您正在设置的属性的名称,我可以,例如,替换您想要的任何方法。

您可以尝试通过例如首先检查旧值是否不可调用,或者不是方法类型描述符等来防止这种情况。以同样的方式,您可以尝试防止人们在setattr中调用函数或在SQL参数中添加引号和分号等等。这实际上与任何其他情况相同。尝试关闭所有通往开门的非法路径要困难得多,而不是一开始就不打开门。

如果名称永远不会来自可能受用户影响的任何内容,该怎么办?

那么,在这种情况下,你为什么要使用eval?没有充分理由使用文字调用setattr

无论如何,当Lattyware表示通常有更好的方法来解决手头的问题时,他几乎肯定会谈论可读性,可维护性和惯用性。但使用这些更好的方法的副作用是你也经常避免任何安全隐患。

90%的时间,解决方案是使用setattr而不是对象。与Javascript不同,它们在Python中并不相同,并且它们并不意味着以相同的方式使用。 dict没有方法,继承或内置特殊名称,因此您不必担心任何问题。它还有一个更方便的语法,您可以说dict而不是d['foo']。它可能更有效率。等等。但最终,使用setattr(o, 'foo')的原因是概念性原因:dict是一个命名的值集合;类实例是模型空间对象的表示,并且它们不是同一个东西。

那么,为什么dict甚至存在?

出于与其他低级功能相同的基本原因,例如能够访问setattrim_func,或拥有func_closuretraceback等模块,或者像其他任何方法一样处理特殊方法,或者impexec

首先,您可以使用这些低级工具构建更高级别的东西。例如,要构建eval,您需要collections.namedtupleexec

其次,您偶尔需要在运行时对代码进行修补,因为您无法在编译时修改它(或者甚至可能看到它),而像setattr这样的工具对于这样做是必不可少的。

setattr功能 - 与setattr非常相似 - 经常被来自Javascript,Tcl或其他一些语言的人滥用。但只要它可以用得很好,你就不想把它从语言中拿出来。 (TOOWTDI不应该这样理解,只能编写一个程序。)

但这并不意味着你应该尽可能地使用这些东西。您不会写eval而不是mylist.__getitem__(slice(1, 10, 2))。有时,能够直接调用mylist[1:10:2]或明确构建__getitem__对象是一个基础,可以让其余的代码更加pythonic,或者本地化一个变通方法以避免感染其余的码。否则,有更清晰,更简单的方法。