如何使用Python清理含风险Python代码的字符串,保障Jinja2模板安全?
防范Jinja2模板中的用户反馈代码注入
首先明确:正常情况下,Jinja2使用{{ feedback }}渲染变量时,默认会开启HTML自动转义,用户输入的Python代码会被当作纯字符串输出,不会被执行。你示例中的代码能执行,大概率是因为开启了自动转义关闭或使用了|safe过滤器。以下是可靠的防护方案:
强制开启自动转义
Jinja2默认对HTML模板自动转义,不要随意禁用。如果你的模板是纯文本类型,也可以手动指定开启转义:from jinja2 import Environment, select_autoescape env = Environment(autoescape=select_autoescape(['html', 'txt'])) template = env.from_string("{{ feedback }}") feedback = "__import__('subprocess').getoutput('tree')" result = template.render(feedback=feedback) # 输出为纯字符串,不会执行代码清理用户输入中的危险关键字
作为辅助防护,过滤掉常见的Python危险关键字,降低攻击者构造恶意代码的可能性:def clean_feedback(content): dangerous_patterns = [ '__import__', 'subprocess', 'os', 'eval', 'exec', 'open', 'file', 'pickle', 'sys' ] for pattern in dangerous_patterns: content = content.replace(pattern, '') return content # 使用示例 raw_feedback = "__import__('subprocess').getoutput('tree')" safe_feedback = clean_feedback(raw_feedback)注意:这种黑名单方式无法覆盖所有攻击变种,仅作为补充防护手段。
使用沙箱环境渲染(针对特殊场景)
如果业务需要处理动态模板内容(非纯字符串展示),用SandboxedEnvironment限制执行权限,禁止访问危险模块:from jinja2.sandbox import SandboxedEnvironment env = SandboxedEnvironment() template = env.from_string("{{ feedback }}") feedback = "__import__('subprocess').getoutput('tree')" result = template.render(feedback=feedback) # 仅输出字符串,代码不会被执行绝对禁止将用户输入作为模板代码
不要直接用用户输入构建模板(比如Template(user_input).render()),这种操作会直接解析用户输入的模板语法,导致严重的代码执行漏洞。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

