SSTI模板注入

攻击流程

Flow of an SSTI attack当用户输入直接嵌入模板而未进行适当的验证或转义时,攻击者可以构建更改模板行为的有效载荷。这可能导致各种意外的服务器端操作,包括:

  • 读取或修改服务器端文件。
  • 执行系统命令。
  • 访问敏感信息(例如,环境变量、数据库凭证)。

漏洞存在验证

使用以下字符串,进行依次拼接观察是否会报错

${{<%[%'"}}\%

如果网站接收这些特殊字符,且正常显示,那么基本没有漏洞:

image-20250325143550004

如果报错,那么说明存在漏洞:

image-20250325143622972

确定模板语言

不同的语言,使用的模板语法不同,常见的有:

Jinjia2/Twig

Jinja2 和 Twig 在语法和行为上相似,仅通过有效载荷响应很难将它们区分开来。

Twig

使用有效载荷{{7*'7'}},输出将是 49

image-20250325113714183

Jinja2

应用程序中使用相同的有效负载,输出将是 7777777

由于 Jinja2 允许在模板中执行 Python 表达式,因此 Jinja2 的安全风险通常源于不安全的编码实践,这些实践允许用户输入在模板中执行,而未经适当的清理。这种漏洞并非源于 Jinja2 本身,而是开发者如何处理模板中的用户输入。

关键漏洞点:

  • 表达式评估:Jinja2 在花括号内评估表达式 {{ }},如果恶意构造,可以执行任意 Python 代码。
  • 模板继承和导入:高级功能如模板继承和宏导入可能被滥用以执行未预期的代码,导致信息泄露或服务器操纵。

image-20250325113732779

Jade/Pug

Pug 的安全漏洞主要源于其能够在模板变量中插入 JavaScript 代码的能力。这个旨在生成动态内容的功能,如果用户输入被嵌入到模板中而没有进行适当的清理,可能会被恶意利用。

主要漏洞点:

  • JavaScript 插值:Pug 允许在模板中直接嵌入 JavaScript,使用插值花括号 #{} 。如果用户输入未经适当清理就被插值,可能导致任意代码执行。
  • 默认转义:Pug 确实为某些输入提供了自动转义,将字符如 <>& 转换为它们的 HTML 实体等效字符,以防止跨站脚本攻击。然而,这种默认行为并不涵盖所有潜在的安全问题,尤其是在处理未转义的插值 !{} 或复杂输入场景时。

Pug(以前称为 Jade)使用不同的语法来处理表达式,这可以被利用来识别其使用。Pug/Jade 在 #{} .中评估 JavaScript 表达式。例如,使用有效载荷#{7*7}会返回 49。

image-20250325113802135

与 Jinja2 或 Twig 不同,Pug/Jade 直接允许在模板中执行 JavaScript,无需额外的分隔符如{{ }}。例如:

image-20250325113818149

Smarty

Smarty 的灵活性允许在模板中动态执行 PHP 函数,这可能会成为一个重大的安全风险。通过模板变量或修饰符执行 PHP 代码的能力应严格控制,以防止未经授权的命令执行。

尝试流程

image-20250327141429830

实操

PHP-Smarty

先确定是否使用了smarty,输入smarty标签,如:{'Hello'|upper},观察结果是否输出Hello,如果是,那就说明使用了smarty,可以进行下一步操作

image-20250325114130765

确定了之后,提供php的命令执行函数构造payload:{system("ls")}

image-20250325114322829

可以看到可以rce了

NodeJS-Pug

在构建有效载荷之前,重要的是要确认应用程序确实使用了 Pug,先构造一个语句进行测试:#{7*7},如果应用程序输出 49,则确认 Pug 正在处理模板。

image-20250325120146525

由于 Pug 允许 JavaScript 插值,那就可以使用 payload #{root.process.mainModule.require('child_process').spawnSync('ls').stdout}

  • root.process 访问 Node.js 中的全局 process 对象,在 Pug 模板内部。
  • mainModule.require('child_process') 动态引入 child_process 模块,绕过可能阻止其常规引入的限制。
  • spawnSync('ls') : 同步执行 ls 命令。
  • .stdout: 捕获命令的标准输出,包括目录列表。

image-20250325120333269

可以执行命令读取文件,实现rce

注:spawnSync不能执行命令+参数的指令类似 ls -al,因为它无法将其分割,而是将其作为一个整体进行执行

spawnSync()的用法:spawnSync(command, [args], [options])

  • command: 这是一个指定要运行的命令的字符串。
  • args: 这是一个传递给命令的字符串参数数组。
  • options: 这是一个可选参数,可以指定各种选项,例如工作目录、环境变量、输入、输出、超时等。

所以正确的写法是:spawnSync('ls', ['-lah']).stdout}

Python-Jinjia2

在构建有效载荷之前,要确认应用程序确实使用了 Jinja2,构造语句:{{7*7}}如果能输出运算结果即证明存在SSTI注入且使用Jinjia2

image-20250325132153218

一旦确认使用 Jinja2,可以使用有效载荷 {{"".__class__.__mro__[1].__subclasses__()[157].__repr__.__globals__.get("__builtins__").get("__import__")("subprocess").check_output("ls")}} 来实现命令执行,其中 __subclasses__()[157] 里面的157是 __subclasses__() 列表中subprocess.Popen 类的索引,此索引是变化的。

细节参考:小迪安全Web安全篇

和NodeJS的Pug一样,不能直接使用 ls -al 这种带参数的指令,需要特殊写法:subprocess.check_output([command, arg1, arg2])

自动化

使用工具:SSTImap进行自动化攻击

预防措施

Jinja2

  • 沙盒模式:在 Jinja2 中启用沙盒环境以限制模板访问不安全函数和属性的能力。这可以防止任意 Python 代码的执行。例如:
from jinja2 import Environment, select_autoescape, sandbox

env = Environment(
    autoescape=select_autoescape(['html', 'xml']),
    extensions=[sandbox.SandboxedEnvironment]
)
  • 输入清理:始终清理输入,以转义或删除可能被解释为代码的危险字符和字符串。当输入直接用于模板表达式时,这一点至关重要。

  • 模板审计:定期审查和审计模板,以发现不安全的编码模式,例如直接嵌入用户输入而不进行清理。

Jade (Pug)

  • 避免直接 JavaScript 取值:限制或避免使用 Pug 在模板中 JavaScript 代码的取值。使用不涉及直接代码执行的其他方法来处理动态内容。例如:

    var user = !{JSON.stringify(user)}
    h1= user.name
    

    谨慎使用 !{} ,因为它允许未转义的输出,这可能会造成危害。建议使用 #{} ,它默认转义 HTML。

  • 验证和清理输入:确保所有用户输入都符合严格的模式,并在模板引擎渲染之前进行清理。这降低了恶意代码执行的风险。

  • 安全配置设置:使用最小化风险的配置选项和环境设置,例如禁用允许脚本执行的功能。

Smarty

  • 禁用 {php} 标签:确保在 Smarty 配置中禁用 {php} 标签,以防止在模板中执行 PHP 代码。

    $smarty->security_policy->php_handling = Smarty::PHP_REMOVE;
    $smarty->disable_security = false;
    
  • 使用安全处理器:如果您必须允许用户自定义模板,请提供一组安全的标签或修饰符,他们可以使用这些标签或修饰符,而不允许直接执行命令或访问 shell。

  • 定期进行安全审查:对模板文件和数据处理逻辑进行安全审查,确保没有使用不安全的做法。定期更新 Smarty 以跟上安全补丁。

模板引擎中的沙箱机制

沙箱机制是一种安全特性,它限制了在模板中执行可能有害的代码。它限制了模板可以执行的操作,例如文件操作或系统命令执行。适当的沙箱机制有助于防止安全漏洞,如 SSTI。

作用:

  • 沙箱机制是一种安全特性,它限制了在模板中执行可能有害的代码。它限制了模板可以执行的操作,例如文件操作或系统命令执行。适当的沙箱机制有助于防止安全漏洞,如 SSTI。
  • 变量和数据访问:控制对全局变量或敏感数据的访问,确保模板无法操纵或泄露关键信息。
posted @ 2025-12-02 09:21  shinianyunyan  阅读(29)  评论(0)    收藏  举报