我正在开发一个Web应用程序,在该应用程序中,用户可以提供字符串,然后服务器将替换变量。
最好使用PEP 3101format()
语法,我正在研究重载Formatter
中的方法以使其对不受信任的输入更加安全。
这是我目前看到的.format()
存在的风险:
- 填充允许您指定任意长度,因此
'{:>9999999999}'.format(..)
可能会耗尽服务器的内存并引起拒绝服务攻击。我需要禁用它。 - 格式化允许您访问对象内部的字段,这很有用,但您可以访问dunder变量并开始进入标准库的位。无法确定哪里会有具有副作用或返回某些机密信息的
getattr()
。我将通过重载get_field()
来白名单属性/索引访问。 - 我自然需要捕获一些异常。
我的假设是:
- 传统的C格式字符串漏洞不适用于Python,因为指定参数是一种边界检查访问集合的方式,而不是直接从线程的堆栈中弹出。
- 我使用的Web框架会转义每个替换为页面模板的变量,并且只要它是输出之前的最后一步,我就可以避免由反转义引起的跨站点脚本攻击。
你怎么想?可能吗?不可能?仅仅是不明智的?
编辑:Armin Ronacher概述了一个丑陋的信息泄漏,如果您没有过滤掉dunder变量访问,则似乎认为保护format()
是可行的:
{local_foo.__init__.__globals__[secret_global]}
小心Python的新式字符串格式化 | Armin Ronacher的思考和写作
个人而言,我在我的产品中实际上并没有使用不受信任的format()
方法,但是为了完整起见,我会进行更新。
replace()
吗? - grcstring.Template
这样的较弱的字符串格式化形式,但是能够引用对象内部的字段在我的情况下非常有用。这是我可以通过构建每个调用中每个参数的每个字段的参数映射来模拟的内容,但最好有一些可以更好地扩展的东西。 - Craig Timpany.format()
功能子集。然后你可以检查格式字符串本身,或者创建自己的模板语言来映射到.format()
格式字符串。 - Davide R.