使用Python的`str.format`方法与服务器端的用户提交模板安全吗?

huangapple go评论71阅读模式
英文:

Is it safe to use python str.format method with user-submitted templates in server-side?

问题

我正在进行一个项目,在该项目中,用户必须能够提交包含占位符的模板,以便稍后呈现以生成动态内容。

例如,用户可能会提交一个类似的模板:

"${item.price} - {item.description} / {item.release_date}"

然后会用真实的值进行格式化。

对于这个目的,使用模板引擎(如Django或Jinja)会需要大量的验证和清理工作,以防止SSTI和XSS,因此我想知道是否可以使用Python的str.format方法创建一个更受限制和更安全的替代方案,因为这个方法不能直接执行Python代码(我相信)。

我的问题是:

在处理用户提交的模板时,使用string.format是否足够安全,还是仍然容易受到注入攻击?
如果不安全,是否有任何实现“安全模板呈现”的替代方法在Python中?

英文:

I am working on project where users must be able to submit templates containing placeholders to be later rendered to generate dynamic content.

For example, a user might submit a template like:

"${item.price} - {item.description} / {item.release_date}"

that would be after formatted with the real values.

Using a template engine (as Django or Jinja) for this purpose would require a lot of validation and sanitizing to prevent SSTI and XSS, so I was wondering if I could use the python str.format method to create a more limited and safer alternative, since this method cannot execute python code directly (I believe).

My question is:

Is using string.format safe enough when dealing with user-submitted templates, or it would still be vulnerable to injection attacks?
If it is not, is there any alternative to implement a "safe template rendering" in python?

答案1

得分: 5

不,通常不安全使用str.format与用户提供的格式字符串。

我脑海中浮现了一个玩具示例,展示了如何使用经过谨慎构造的格式字符串,str.format可以轻松地从您的服务器中泄露敏感信息。也可能存在其他攻击途径。

这种攻击仅依赖于攻击者知道(或猜测)提供给str.format的参数的类型。

运行此代码将打印服务器上定义的所有环境变量:

import os

class Foo:
    def foo(self):
        pass

user_format = "{f.foo.__globals__[os].environ}"
print(user_format.format(f=Foo()))

对于Django,此格式字符串将打印整个设置模块,包括您的数据库密码、签名密钥和所有可利用信息的各种位:

user_format = "{f.foo.__globals__[sys].modules[myapp.settings].__dict__}"
英文:

No, it is not generally safe to use str.format with user-provided format strings.

Off the top of my head, I came up with this toy example of how str.format with a carefully constructed format string can easily leak sensitive information from your server. Other attack vectors may also exist.

This attack only relies on the attacker knowing (or guessing) the of types of the arguments being supplied to str.format.

Running this code will print all environment variables defined on the server:

import os

class Foo:
    def foo(self):
        pass

user_format = "{f.foo.__globals__[os].environ}"
print(user_format.format(f=Foo()))

Specific to Django, this format string will print your entire settings module, complete with your DB passwords, signing keys, and all sorts of other bits of exploitable information:

user_format = "{f.foo.__globals__[sys].modules[myapp.settings].__dict__}"

huangapple
  • 本文由 发表于 2023年7月28日 04:34:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783239.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定