一、服务器模板注入
服务器模板注入(Server-side template injection)是当攻击者能够用本地的模板语法去注入一个恶意的payload,然后再服务器端执行该模板的攻击手法。
模板引擎是通过将固定模板与多变数据结合起来生成html网页的一种技术,当用户直接输入数据到模板不作任何过滤的时,可能会发生服务端模板注入攻击。这使得攻击者可以注入任何模板指令来操控服务器模板引擎,从而使整个服务器被控制。
顾名思义,服务器模板注入和SQL注入大同小异,但SSTI是发生在服务器端的,更加危险。
服务器模板注入的危害性往往取决于所使用的模板引擎以及应用程序的使用方式,很少有情况不会带来真正的安全风险,但绝大多数情况下都是致命性的影响。最严重的的情况是攻击者可以进行RCE(远程代码执行),完全控制服务器端,并进行内网攻击;即使在无法完全进行RCE的情况下,攻击者也能将SSTI和其他漏洞进行“组合拳”攻击,比如可能读取服务器上的敏感文件等。
二、为什么需要服务器模板
简单来说,页面上的数据需要不断更新,即为渲染。后台语言通过一些模板引擎生成HTML的过程。(常见的模板渲染引擎Jade, YAML )
因为Web Application 最终是要落实到HTML、CSS、JavaScript等用户界面上的,有一种情况是,每一个页面都需要特殊的逻辑,随着应用功能的增加,而且彼此之间没有同步,比如你改了站点的布局风格,那么随之就要修改成百上千的HTML文件。谁能忍?
既然如此多的HTML具有一定的逻辑联系,何不使用代码生成代码?于是后端模板语言诞生了。分别有前端渲染和后端(服务器)渲染,区别是:
后端渲染是将一些模板规范语言翻译成如上三种语言回传给前端;而前端渲染则是将整个生成逻辑代码全部回传前端,再由客户端生成用户界面。
所以服务器模板提供了一种更加简单的方法来管理动态生成HTML,一个demo演示
前端:
<html>
<head>
<title>{
{title}}</title>
</head>
<body>
<form method="{
{method}}" action="{
{action}}">
<input type="text" name="user" value="{
{username}}">
<input type="password" name="pass" value="">
<button type="submit">submit</button>
</form>
<p>Used {
{mikrotime(true) - time}}</p>
</body>
</html>
后端:
$template Engine=new TempLate Engine() ;
$template=$template Engine-load File('login.tpl') ;
$template->assign('title', 'login') ;
$template->assign('method', 'post') ;
$template->assign('action', 'login.php') ;
$template->assign('username', get Username From Cookie() ) ;
$template->assign('time', microtime(true) ) ;
$template->show() ;
首先加载login.tpl模板文件,然后对与模板中名称相同的变量赋值(大括号里的变量),然后调用show()函数,相应的替换它们的内容并输出HTML代码。
三、漏洞原理
当用户直接输入数据到模板不作任何过滤的时,可能会发生服务端模板注入攻击。
仅仅提供了占位符,并在其中呈现动态内容的静态模板通常不会受到SSTI攻击。经典的示例是一封电子邮件,其中用每个用户的名字向他们致意,例如以下Twig模板:
$output = $twig->render("Dear {first_name},", array("first_name" => $user.first_name) );
此时无法进行SSTI攻击,因为用户的名字仅仅是作为数据传入模板中。
然而,由于模板只是字符串,web开发者有时会在生成HTML之前,直接将用户的输入呈现到模板中。简单的以上述demo为例,此处用户能够在发送邮件之前自定义部分邮件。例如,他们也许能够选择使用的名称:
$output = $twig->render("Dear " . $_GET['name']);
在此示例中,不是使用静态值传递到模板中,而是使用GET参数名称动态生成模板本身的一部分。 在服务器端对模板语法进行动态生成时,这可能使攻击者可以将服务器端模板注入有效负载放置在name参数内,如下所示:
http://vulnerable-website.com/?name={
{payload}}
诸如此类的漏洞有时是由不熟悉安全隐患的人由于不良模板设计导致的意外所致。 就像上面的示例一样,可能会看到不同的组件,其中一些包含用户输入,这些用户输入已直接输出到并嵌入到模板中。 在某些方面,这类似于编写不当的预编译语句中发生的SQL注入漏洞。
但是,有时这种行为实际上是有意实施的。 例如,某些网站故意允许某些特权用户(例如内容编辑器)通过设计来编辑或提交自定义模板。 如果攻击者能够利用这种特权来破坏帐户,则显然会带来巨大的安全风险。
四、利用过程
- 发现漏洞
寻找SSTI漏洞需要代码审计或者直接黑盒引发报错,最简单的方法是通过注入模板表达式中常用的特殊字符来Fuzz,例如:$ { {<%[%'“}}%\。如果引发了报错,则表明服务器模板可能存在漏洞。SSTI漏洞通常发生在两个不同的上下文中,所以要根据特定的上下文来进行Fuzz。
大多数模板语言都允许直接使用HTML标记或使用模板的语法自由输入内容,这些模板将在发送HTTP响应之前在后端呈现为HTML。例如,在Freemarker中,render('Hello'+ username)行将呈现为Hello Carlos之类的东西。
有时可以将其用于XSS,实际上经常被误认为是简单的XSS漏洞。但是,通过上述的方法注入模板表达式的特殊字符,我们可以测试这是否也是服务器端模板注入攻击的潜在入口点。
例如,如下就是一个有漏洞的模板:
render('Hello' + username);
攻击者可以通过请求URL来验证SSTI攻击:
http://vulnerable-website.com/?username=${7*7}
如果结果输出包含Hello 49,则表明该数学运算表达式正在服务器端进行渲染生成。这是服务器端模板注入漏洞的典型证明。
另外,漏洞可能将用

本文深入解析服务器模板注入(SSTI)攻击,涵盖概念、利用过程、实验案例及防御策略,揭示模板引擎的安全风险。
最低0.47元/天 解锁文章
1840

被折叠的 条评论
为什么被折叠?



