SSTI模板注入 2018-01-01 02:18:27 Steven Xeldax ``` 最近看到模板注入感觉很有意思,所以这里就整理了关于模板注入的一些知识。 不过模板注入有很多所以这里只是了解一下什么是模板注入,不建议去尝试手工注入,因为模板的种类有很多,python,php就有很多,所以建议还是用工具,github上搜tqlmap就可以。 原文:https://www.anquanke.com/post/id/82856 ``` ## 模板注入原理 模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程,这里我们使用 PHP 模版引擎Twig 作为例子来说明模板注入产生的原理。考虑下面这段代码: ``` <?php require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php'; Twig_Autoloader::register(true); $twig=newTwig_Environment(newTwig_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=newTwig_Environment(newTwig_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=newTwig_Environment(newTwig_Loader_String()); $output=$twig->render("Hello {$_GET['name']}");// 将用户输入作为模版内容的一部分 echo$output; ``` 在 Twig 模板引擎里, {{var}} 除了可以输出传递的变量以外,还能执行一些基本的表达式然后将其结果作为该模板变量的值,例如这里用户输入 name={{2*10}} ,则在服务端拼接的模版内容为: ``` Hello{{2*10}} ``` Twig 模板引擎在编译模板的过程中会计算 {{2*10}} 中的表达式 2*10 ,会将其返回值 20 作为模板变量的值输出,如下图: 现在把测试的数据改变一下,插入一些正常字符和 Twig 模板引擎默认的注释符,构造 Payload 为: ``` IsVuln{# comment #}{{2*8}}OK ``` 实际服务端要进行编译的模板就被构造为: ``` HelloIsVuln{# comment #}{{2*8}}OK ``` 这里简单分析一下,由于 {# comment #} 作为 Twig 模板引擎的默认注释形式,所以在前端输出的时候并不会显示,而 {{2*8}} 作为模板变量最终会返回 16 作为其值进行显示,因此前端最终会返回内容 Hello IsVuln16OK ,如下图:  通过上面两个简单的示例,就能得到 SSTI 扫描检测的大致流程(这里以 Twig 为例): 