英文:
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__}"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论