【渗透测试】服务端模板注入攻击 (SSTI)


一、模板注入与常见Web注入

就注入类型的漏洞来说,常见 Web 注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。注入漏洞的实质是服务端接受了用户的输入,未过滤或过滤不严谨执行了拼接了用户输入的代码,因此造成了各类注入。下面这段代码足以说明这一点:

// SQL 注入
$query = "select * from sometable where id=".$_GET['id'];
mysql_query($query);

------------- 华丽的分割线 -------------

// 模版注入
$temp->render("Hello ".$_GET['username']);

而服务端模板注入和常见Web注入的成因一样,也是服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

二、模板注入原理

模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程,这里我们使用 PHP 模版引擎 Twig 作为例子来说明模板注入产生的原理。考虑下面这段代码:

<?php
require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
Twig_Autoloader::register(true);

$twig = new Twig_Environment(new Twig_Loader_String());
$output = $twig->render("Hello {{name}}", array("name" => $_GET["name"]));  // 将用户输入作为模版变量的值
echo $output;

使用 Twig 模版引擎渲染页面,其中模版含有 {{name}}变量,其模版变量值来自于 GET 请求参数 $_GET["name"]。显然这段代码并没有什么问题,即使你想通过 name 参数传递一段 JavaScript 代码给服务端进行渲染,也许你会认为这里可以进行 XSS,但是由于模版引擎一般都默认对渲染的变量值进行编码和转义,所以并不会造成跨站脚本攻击:
在这里插入图片描述
但是,如果渲染的模版内容受到用户的控制,情况就不一样了。修改代码为:

<?php
require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
Twig_Autoloader::register(true);

$twig = new Twig_Environment(new Twig_Loader_String());
$output = $twig->render("Hello {$_GET['name']}");  // 将用户输入作为模版内容的一部分
echo $output;

上面这段代码在构建模版时,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递 JavaScript 代码,用户输入会原样输出,测试结果显而易见:
在这里插入图片描述
对比上面两种情况,简单的说服务端模板注入的形成终究还是因为服务端相信了用户的输出而造成的(Web安全真谛:永远不要相信用户的输入!)。当然了,第二种情况下,攻击者不仅仅能插入 JavaScript 脚本,还能针对模板框架进行进一步的攻击,此部分只说明原理,在后面会对攻击利用进行详细说明和演示。

三、模板注入检测

上面已经讲明了模板注入的形成原来,现在就来谈谈对其进行检测和扫描的方法。如果服务端将用户的输入作为了模板的一部分,那么在页面渲染时也必定会将用户输入的内容进行模版编译和解析最后输出。

借用本文第二部分所用到的代码:

<?php
require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
Twig_Autoloader::register(true);

$twig = new Twig_Environment(new Twig_Loader_String());
$output = $twig->render("Hello {$_GET['name']}");  // 将用户输入作为模版内容的一部分
echo $output;

在 Twig 模板引擎里, {{ var }}除了可以输出传递的变量以外,还能执行一些基本的表达式然后将其结果作为该模板变量的值,例如这里用户输入 `n``ame={{2*10}}```,则在服务端拼接的模版内容为:

Hello {{2*10}}

Twig 模板引擎在编译模板的过程中会计算 {{2*10}}中的表达式 2*10,会将其返回值 20 作为模板变量的值输出,如下图:
在这里插入图片描述
现在把测试的数据改变一下,插入一些正常字符和 Twig 模板引擎默认的注释符,构造 Payload 为:

IsVuln{# comment #}{{2*8}}OK

实际服务端要进行编译的模板就被构造为:

Hello IsVuln{# comment #}{{2*8}}OK

这里简单分析一下,由于{# comment #}作为 Twig 模板引擎的默认注释形式,所以在前端输出的时候并不会显示,而{{2*8}}作为模板变量最终会返回 16 作为其值进行显示,因此前端最终会返回内容 Hello IsVuln16OK ,如下图:
在这里插入图片描述
通过上面两个简单的示例,就能得到 SSTI 扫描检测的大致流程(这里以 Twig 为例):
在这里插入图片描述
同常规的 SQL 注入检测,XSS 检测一样,模板注入漏洞的检测也是向传递的参数中承载特定 Payload 并根据返回的内容来进行判断的。每一个模板引擎都有着自己的语法,Payload 的构造需要针对各类模板引擎制定其不同的扫描规则,就如同 SQL 注入中有着不同的数据库类型一样。

简单来说,就是更改请求参数使之承载含有模板引擎语法的 Payload,通过页面渲染返回的内容检测承载的 Payload 是否有得到编译解析,有解析则可以判定含有 Payload 对应模板引擎注入,否则不存在 SSTI。

原文链接:https://blog.knownsec.com/2015/11/server-side-template-injection-attack-analysis/
参考文章:https://xz.aliyun.com/t/9026

### 模板注入攻击原理 模板注入是一种常见的Web应用安全漏洞,其核心在于允许恶意用户通过特定输入向Web应用程序的模板引擎传递未过滤的内容。如果这些内容被解释并执行,则可能引发严重的安全隐患。例如,在Go语言开发中,尽管框架提供了许多内置功能来帮助开发者创建高效的应用程序[^1],但如果未能正确处理用户输入,仍然可能发生此类问题。 当模板引擎接收到未经验证的数据时,可能会将其作为代码片段解析而不是纯文本显示。这使得攻击者能够利用此行为嵌入恶意脚本或其他危险指令,从而控制页面渲染逻辑甚至远程执行命令。这种类型的攻击尤其常见于支持动态内容生成的服务端环境中[^2]。 ### 防御方法 为了防止模板注入的发生,应采取以下措施: #### 输入验证与清理 确保所有来自外部源(如HTTP请求参数、表单提交等)的数据都经过严格的校验流程。只接受预期格式内的值,并移除任何潜在有害字符或结构。对于字符串型字段来说,可以通过正则表达式匹配限定合法范围;而对于复杂对象,则需逐级深入检查直至最底层属性均满足条件为止[^3]。 ```python import re def sanitize_input(user_data): pattern = r'^[a-zA-Z0-9\s]+$' # 假设我们仅允许字母数字及空格 if not re.match(pattern, user_data): raise ValueError("Invalid input detected.") return user_data ``` #### 使用沙盒环境 某些高级别的防护机制会涉及运行时隔离技术——即把待评估的风险操作放置在一个受限权限下的独立进程中完成计算任务。这样即使存在缺陷也能有效遏制危害扩散至更广泛区域之外。 #### 更新依赖关系 定期审查项目所使用的第三方库版本状态,及时替换掉已知存在问题的老化组件。因为很多流行开源软件包本身也可能携带隐蔽风险点,所以保持最新稳定发行版有助于减少暴露面。 ```bash go get -u all ``` 上述命令可以帮助升级Golang项目的全部子模块到它们各自的最近一次发布标记处。 ### 结论 综上所述,通过对用户输入实施全面细致的安全策略以及合理配置相关工具链设置,可以在很大程度程度上规避因模板注入而导致的各种不良后果。同时也要意识到网络安全是一个持续改进的过程,随着新型威胁不断涌现,相应的应对方案也需要与时俱进加以完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多学点技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值