Python的字符串.format()可以安全地用于不受信任的格式字符串吗?

Cra*_*any 15 python security

我正在开发一个Web应用程序,用户可以在其中提供服务器然后将变量替换为的字符串.

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

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

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

我的假设是:

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

你的想法是什么?可能?不可能?真的不明智?


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

{local_foo.__init__.__globals__[secret_global]}

http://lucumr.pocoo.org/2016/12/29/careful-with-str-format/

(就个人而言,我实际上并没有在我的产品中使用不受信任的format()路由,但为了完整性而更新)

roo*_*ook 8

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

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

查看python格式字符串规范并禁止用户使用正则表达式来禁用该功能.

  • 或者更好的是,*允许*您希望支持的功能,因此当您使用新的(也可能是危险的)格式选项升级到新版本的Python时,您不会被抓住. (12认同)