在 Python 3 中使用用户输入进行字符串格式化的安全方法和实践有哪些?

Bri*_*ian 7 python security user-input string-formatting string-interpolation

我的理解

从各种来源,我了解到 Python 3(f 字符串为 3.6+)中有四种主要的字符串格式化/插值技术:

  1. 使用 进行格式化%,与 C 类似printf
  2. 方法str.format()
  3. 格式化字符串文字/f 字符串
  4. string来自标准库模块的模板字符串

我的使用知识主要来自Python String Formatting Best Practices(来源A

  • str.format()是作为 -style 的更好替代品而创建的%,因此后者现在已过时
    • 但是,如果未正确处理用户给定的格式字符串,则str.format()容易受到攻击
  • f 字符串str.format()仅允许字符串文字的类似行为,但编写起来更短,实际上是用于连接的某种程度优化的语法糖
  • 处理用户输入时,模板字符串比str.format()(第一个源中演示的)和其他两种方法(第一个源中隐含的)更安全

据我了解,上述漏洞来自str.format()于可在任何普通字符串上使用的方法,其中定界大括号是字符串数据本身的一部分。包含大括号分隔的替换字段的恶意用​​户输入可以提供给访问环境属性的方法。我相信这与其他格式化方式不同,在其他格式化方式中,程序员是唯一可以向预格式化字符串提供变量的人。例如,f 字符串与 but 具有相似的语法str.format(),因为 f 字符串是文字,并且插入的值是通过类似串联的行为单独计算的,所以它们不容易受到相同的攻击(来源 B)。-formatting%和 Template 字符串似乎也只提供供程序员替换的变量;指出的主要区别是模板的功能更加有限。

我的困惑

我看到很多人都强调其脆弱性,str.format()这让我产生了在使用其他技术时应该警惕什么的问题。来源 A将模板字符串描述为上述方法中最安全的方法,“因为它们降低了复杂性”:

其他字符串格式化技术的更复杂的格式化迷你语言可能会给您的程序带来安全漏洞。

  1. 是的,看起来 f 字符串并不像源 A所暗示的str.format()那样容易受到攻击,但是是否存在已知的关于f 字符串安全性的担忧?这种担忧是否更像是针对未知漏洞和意外交互的风险缓解?

我不熟悉 C,也不打算使用笨重的%/ printf- 风格的格式,但我听说 Cprintf有其自身的潜在漏洞。此外,来源 A 和 B似乎都暗示这种方法缺乏安全性。来源 B 中的最佳答案说:

当格式字符串依赖于不受信任的数据时,字符串格式化可能会很危险。因此,在使用 str.format() 或 %-formatting 时,使用静态格式字符串或在应用格式化程序函数之前清理不受信任的部分非常重要。

  1. -style 字符串是否%存在已知的安全问题?
  2. 最后,应该使用哪些方法以及如何防止基于用户输入的攻击(例如使用正则表达式过滤输入)?
    • 更具体地说,模板字符串真的是更安全的选择吗?f 字符串是否可以同样轻松、安全地使用,同时授予更多功能?

Gil*_*hen 1

无论您选择哪种格式,任何格式和库都可能有其自身的缺点和漏洞。您需要问自己的更大问题是风险因素和您面临的情况是什么,以及您将采取什么措施。首先问问自己:是否会出现用户或某种外部实体(例如外部系统)向您发送格式字符串的情况?如果答案是否定的,则没有风险。如果答案是肯定的,那么您需要看看是否需要这样做。如果没有 - 将其删除以消除风险。如果需要,您可以执行基于白名单的输入验证,并从允许的字符列表中排除所有特定于格式的特殊字符,以消除风险。例如,任何格式字符串都不能传递 ^[a-zA-Z0-9\s]*$ 通用正则表达式。

因此底线是:使用哪种格式字符串类型并不重要,真正重要的是您如何使用它以及如何减少和消除它被篡改的风险。

  • 谢谢您的指导。我发现我可能过于仔细地关注每种格式的细节。您提供的总体心态使选择看起来不那么势不可挡。我想我没有具体说明,我也对每种格式的工作方式比较好奇,这些方式使得某些安全问题适用。这些消息来源让我担心我错过了一些东西。搜索引擎中缺乏相关结果告诉我,除了 str.format() 之外,可能没有其他重大问题。正如终结者评论的那样,我可能应该检查文档以获取更具体的信息。 (2认同)