在介绍服务器模板注入之前,我们先科普一下模板引擎。模版引擎广泛用于从展示层分离程序逻辑,维基、博客和内容管理系统都倾向于使用模版引擎。不仅因为这是良好的编程实践,也因为它能够使不甚了解HTML知识的人员轻松地更新和维护网站内容或编写HTML格式的电子邮件。它也让专业的网页设计师利用这些代码快速而高效地建站。流行的模板包括Twig、Jade以及XWike Enterprise。一些引擎使用简单的字符串,占位符由数据替换。例如一封电子邮件模板开头可能是 "Dear {user_firstname}" ,在模板引擎中,"user_firstname" 则由底层数据库中的’first name‘所取代,还有些则包括额外的灵活性,诸如用for-each循环、递归宏和嵌入式表达来提供更丰富的功能。
一、模板注入与常见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 代码,用户输入会原样输出。
对比上面两种情况,简单的说服务端模板注入的形成终究还是因为服务端相信了用户的输出而造成的。当然了,第二种情况下,攻击者不仅仅能插入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 }} 除了可以输出传递的变量以外,还能执行一些基本的表达式然后将其结果作为该模板变量的值,例如这里用户输入 name={{2*10}} ,则在服务端拼接的模版内容为:
Hello {{2*10}}
Twig 模板引擎在编译模板的过程中会计算{{210}} 中的表达式 210,会将其返回值20作为模板变量的值输出。从这些简单的例子中,我们可以归纳出模板注入漏洞的检测的基本方法:它同常规的SQL注入检测,XSS检测一样,也是向传递的参数中承载特定Payload并根据返回的内容来进行判断的。每一个模板引擎都有着自己的语法,Payload 的构造需要针对各类模板引擎制定其不同的扫描规则,就如同SQL注入中有着不同的数据库类型一样。简单来说,就是更改请求参数使之承载含有模板引擎语法的Payload,通过页面渲染返回的内容检测承载的 Payload 是否有得到编译解析,有解析则可以判定含有Payload对应模板引擎注入,否则不存在SSTI。
四、SSTI漏洞利用与实践
在开始靶机渗透之前,我先给大家介绍一下今天要用到的一个工具Tplmap。它是一个python工具,可以通过使用沙箱转义技术找到代码注入和服务器端模板注入(SSTI)漏洞。该工具能够在许多模板引擎中利用SSTI来访问目标文件或操作系统。一些受支持的模板引擎包括PHP代码评估、Ruby代码评估、JaveScript代码评估)、Python代码评估,ERB,Jinja2和Tornado。该工具可以执行对这些模板引擎的盲注入,并具有执行远程命令的能力。更多相关介绍大家可以自行百度。
今天的靶机名字叫muzzybox,是vulnhub中蛮有意思的靶机。把每个靶机都从头到尾把writeup复述一遍是比较费时费力的,如果靶机渗透的前后过程存在必然的依赖关系的话,复述是很有必要的事情。
**此次的渗透机IP:192.168.1.113
**
靶机的IP:192.168.1.114
**** 这里我主要是讲服务器端模板注入漏洞的利用与渗透,这个靶机的三个flag是相互独立的,该漏洞是第三个flag,我们就从这里开始讲起。先看看我们在靶机上发现了什么吧,下面是靶机提示我们访问这个URL。
那么,我们是否可以验证一下是否存在SSTI漏洞呢?遇到这样格式的URL,一般思路是先考虑是否注入漏洞。我们试试看。
将url的name后面写入“{{78}}”,页面返回了56,服务器后端确实把“78”给解析了!说明靶机存在服务器模板注入漏洞。这里我们借助先前介绍的扫描服务器端模板注入漏洞的开源工具Tplmap进行渗透。时间不早了,明天还要赶早到单位,今天就到此了。我将在后续文章中详细介绍这个渗透过程。2020,让我们一起加油吧!
参考: