25

我正在开发一个网络应用程序,用户将能够提供服务器然后将变量替换为的字符串。

最好我想使用PEP 3101 format()语法,并且我正在研究覆盖方法的可行性,Formatter以使其对不受信任的输入安全。

以下是我可以看到的风险.format()

  • 填充可让您指定任意长度,因此'{:>9999999999}'.format(..)可能会使服务器内存不足并成为 DOS。我需要禁用它。
  • Format 允许您访问对象内部的字段,这很有用,但令人毛骨悚然的是您可以访问 dunder 变量并开始钻研标准库的一些内容。不知道哪里可能getattr()有副作用或返回一些秘密。我会通过覆盖将属性/索引访问列入白名单get_field()
  • 自然,我需要捕获一些异常。

我的假设是:

  • 传统的 C 格式字符串漏洞都不适用于 Python,因为指定参数是对集合的边界检查访问,而不是直接从线程的堆栈中弹出。
  • 我正在使用的 Web 框架转义了替换到页面模板中的每个变量,只要它是输出前的最后一站,我就可以安全地避免因反转义而出现的跨站点脚本攻击。

你觉得呢?你有没有什么想法?可能的?不可能的?只是不明智?


编辑:如果您不过滤掉 dunder 变量访问,Armin Ronacher 概述了一个令人讨厌的信息泄漏,但似乎认为安全format()是可行的:

{local_foo.__init__.__globals__[secret_global]}

小心 Python 的新型字符串格式 阿明·罗纳赫的思想和著作

就个人而言,我实际上并没有format()在我的产品中走不受信任的路线,而是为了完整性而进行更新

4

2 回答 2

8

好本能。是的,能够提供任意格式字符串的攻击者是 python 下的一个漏洞。

  • 拒绝服务可能是最容易解决的问题。在这种情况下,限制字符串的大小或字符串中的运算符数量将缓解此问题。应该有一个设置,即没有合理的用户需要生成一个具有比 X 更多变量的字符串,并且这个计算量没有被 DoS 攻击利用的风险。
  • 能够访问对象内的属性可能很危险。但是,我认为Object父类没有任何有用的信息。提供给格式的对象必须包含一些敏感的东西。在任何情况下,这种类型的符号都可以用正则表达式来限制。
  • 如果格式字符串是用户提供的,那么用户可能需要知道错误消息以进行调试。但是,错误消息可能包含敏感信息,例如本地路径或类名。确保限制攻击者可以获得的信息。

查看python 格式字符串规范并禁止您不希望用户使用正则表达式的功能。

于 2013-03-13T16:14:56.607 回答
2

这个简单的格式化程序覆盖阻止用户访问属性。它仍然允许格式化和转换类型。

from string import Formatter
class SafeFormatter(Formatter):
        def get_field(self, field_name, args, kwargs):
            if '.' in field_name or '[' in field_name:
                raise Exception('Invalid format string.')
            return super().get_field(field_name,args,kwargs)

form = SafeFormatter()
fname = form.format(format,num=1,id='hello')
于 2020-03-04T11:36:33.187 回答