9

setattr并且getattr有点进入我的编程风格(主要是科学的东西,我对 python 的了解是自说自话的)。

考虑到这一点execeval继承潜在的危险,因为在某些情况下它们可能会导致安全问题,我想知道对于setattr相同的论点是否被认为是有效的。(关于getattr我发现这个问题包含一些信息 - 尽管论证不是很有说服力。)

据我所知,setattr可以不用担心太多,但老实说我不太相信我的python知识,如果我错了,我想尝试改掉使用的习惯setattr.

非常感谢任何输入!

4

1 回答 1

12

首先,它肯定可以更容易地解决现有的安全漏洞。

例如,假设您有执行exec, eval, SQL 查询或通过字符串格式构建的 URL 等的代码。假设您正在传递、说locals()或过滤__dict__到格式化命令或作为eval上下文或其他任何东西。使用setattr显然会扩大安全漏洞,使我更容易找到攻击代码的方法,因为您不再确定要传递给这些函数的内容。

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

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

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

如果名称从不来自任何可能受用户影响的东西怎么办?

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

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

90% 的情况下,解决方案是使用 adict而不是对象。与 Javascript 不同,它们在 Python 中不是一回事,而且它们的使用方式也不相同。Adict没有方法、继承或内置的特殊名称,因此您不必担心这些。它还具有更方便的语法,您可以在其中说d['foo']而不是setattr(o, 'foo'). 而且它可能更有效。等等。但归根结底,使用 a 的dict原因是概念上的原因:adict是值的命名集合;类实例是模型空间对象的表示,它们不是一回事。

那么,为什么会setattr存在呢?

它的存在与其他低级功能相同的基本原因,例如能够访问im_funcor func_closure,或者具有类似tracebackand的模块imp,或者像对待任何其他方法一样处理特殊方法,或者就此而言execand eval

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

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

这个setattr特性——很像eval——经常被来自 Javascript、Tcl 或其他一些语言的人滥用。但只要它可以永久使用,您就不想将其从语言中删除。(TOOWTDI 不应该被理解为只能编写一个程序。)

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

于 2012-12-21T00:05:08.010 回答