SSTI(以Twig模板引擎为例)
一、模板注入与常见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 作为例子来说明模板注入产生的原理。考虑下面这段代码:
1 <?php
2 require_once '../Twig-1.35.3/lib/Twig/Autoloader.php';
3 Twig_Autoloader::register(true);
4 $twig = new Twig_Environment(new Twig_Loader_String());
5 $output = $twig->render("Hello {{name}}", array("name" => $_GET["name"])); // 将用户输入作为模版变量的值
6 echo $output;
使用 Twig 模版引擎渲染页面,其中模版含有 {{name}} 变量,其模版变量值来自于 GET 请求参数 $_GET["name"] 。显然这段代码并没有什么问题,即使你想通过 name 参数传递一段 JavaScript 代码给服务端进行渲染,也许你会认为这里可以进行 XSS,但是由于模版引擎一般都默认对渲染的变量值进行编码和转义,所以并不会造成跨站脚本攻击:

但是,如果渲染的模版内容受到用户的控制,情况就不一样了。修改代码为:
1 <?php
2 require_once '../Twig-1.35.3/lib/Twig/Autoloader.php';
3 Twig_Autoloader::register(true);
4 $twig = new Twig_Environment(new Twig_Loader_String());
5 $output = $twig->render("Hello {$_GET['name']}"); // 将用户输入作为模版内容的一部分
6 echo $output;
上面这段代码在构建模版时,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递 JavaScript 代码,用户输入会原样输出,测试结果显而易见:

对比上面两种情况,简单的说服务端模板注入的形成终究还是因为服务端相信了用户的输入而造成的(Web安全真谛:永远不要相信用户的输入!)。当然了,第二种情况下,攻击者不仅仅能插入 JavaScript 脚本,还能针对模板框架进行进一步的攻击,此部分只说明原理,在后面会对攻击利用进行详细说明和演示。
三、模板注入检测
上面已经讲明了模板注入的形成原来,现在就来谈谈对其进行检测和扫描的方法。如果服务端将用户的输入作为了模板的一部分,那么在页面渲染时也必定会将用户输入的内容进行模版编译和解析最后输出。
借用本文第二部分所用到的代码:
1 <?php
2 require_once '../Twig-1.35.3/lib/Twig/Autoloader.php';
3 Twig_Autoloader::register(true);
4 $twig = new Twig_Environment(new Twig_Loader_String());
5 $output = $twig->render("Hello {$_GET['name']}"); // 将用户输入作为模版内容的一部分
6 echo $output;
在 Twig 模板引擎里,{{ var }} 除了可以输出传递的变量以外,还能执行一些基本的表达式然后将其结果作为该模板变量的值,例如这里用户输入 name={{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。
四、小结
本文简单介绍服务端模版注入漏洞如常规 Web 注入漏洞之间的关系,分析了其产生的原理,并以 PHP 模板引擎 Twig 为例讲解了 SSTI 常规的扫描和检测方法。虽然说 SSTI 并不广泛存在,但如果开发人员滥用模板引擎,进行不安全的编码,这样 Web 应用就可能出现 SSTI,并且根据其模板引擎的复杂性和开发语言的特性,可能会造成非常严重的问题。
在后续的文章中会针对各语言流行的模板引擎做一个较为详细的研究和分析,给出对应的可利用点和方法。
来自FreeBuf黑客与极客(FreeBuf.COM)
http://blog.knownsec.com/2015/11/server-side-template-injection-attack-analysis/
SSTI(以Twig模板引擎为例)的更多相关文章
- opencart 引入 TWIG 模板引擎
1.首先将 twig 包放入 system\library 目录. 2.在 system/startup.php 文件最后添加引入语句. require_once(DIR_SYSTEM . 'lib ...
- 构建自己的PHP框架(Twig模板引擎)
完整项目地址:https://github.com/Evai/Aier Twig 模板引擎 模版引擎 twig 的模板就是普通的文本文件,也不需要特别的扩展名,.html .htm .twig 都可以 ...
- 原生twig模板引擎详解(安装使用)
最近在学习SSTI(服务器模板注入),所以在此总结一下 0x00 Twig的介绍 什么是Twig? Twig是一款灵活.快速.安全的PHP模板引擎. Twig的特点? 快速:Twig将模板编译为纯粹的 ...
- yii2 使用twig 模板引擎
yii2 默认使用PHP 和html 混合的方式来写视图层,但我个人还是喜欢纯模板语言的方式.而且已经非常习惯使用twig的语法,最近想使用yii2进行开发,所以还是选择使用twig视图引擎. git ...
- twig 模板引擎使渲染视图更加优雅
在使用 laravel 的时候接触过 blade 模板引擎.在学习的时候,接触到了另外一个强大的模板引擎:twig 官网:https://twig.sensiolabs.org/ 中文手册:http: ...
- symfony2 twig模板引擎
1.基本语法 Says something:{{ }} Does something:{% %} Comment something:{# #} {% extends "App ...
- laravel Blade 模板引擎
与视图文件紧密关联的就是模板代码,我们在视图文件中通过模板代码和 HTML 代码结合实现视图的渲染.和很多其他后端语言不同,PHP 本身就可以当做模板语言来使用,但是这种方式有很多缺点,比如安全上的隐 ...
- 第115天:Ajax 中artTemplate模板引擎(一)
一.不分离与分离的比较 1.前后端不分离,以freemarker模板引擎为例,看一下不分离的前后端请求的流程是什么样的? 从上图可以看出,前后端开发人员的工作耦合主要在(3)Template的使用.后 ...
- thinkphp5.1 - twig模板-全局变量
thinkphp5.1 - twig模板-全局变量我们在定义 ccs 之类的静态文件的时候,经常会使用<link rel="stylesheet" href="__ ...
随机推荐
- 任务日历关联(Project)
<Project2016 企业项目管理实践>张会斌 董方好 编著 有时候吧,一件大事是由N件小事组成的,而这N件小事当中,不是每件事都可以在周末停下来的,当然也不是所有的事都必须在周末完成 ...
- Go语言核心36讲(Go语言实战与应用二十七)--学习笔记
49 | 程序性能分析基础(下) 在上一篇文章中,我们围绕着"怎样让程序对 CPU 概要信息进行采样"这一问题进行了探讨,今天,我们再来一起看看它的拓展问题. 知识扩展 问题 1: ...
- java 输入输出IO流 字节流| 字符流 的缓冲流:BufferedInputStream;BufferedOutputStream;BufferedReader(Reader in);BufferedWriter(Writer out)
什么是缓冲流: 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率. 图解: 1.字节缓冲流BufferedInputStr ...
- Python3 json &pickle 数据序列化
json 所有语言通用的信息交换格式 json.dumps()将list列表.dict字典.元组.函数等对象转换为可以存储的字符格式存入文件 json.dump(数据对象名,已以写方式打开的对象) 直 ...
- Vue-Router(一)
Vue-Router(一) 简介 vue-router是Vuejs的官方推荐路由,让用 Vue.js 构建单页应用变得非常容易.目前Vue路由最新的版本是4.x版本. vue-router是基于路由和 ...
- NDK编译可执行文件在Android 中运行显示error: only position independent executables (PIE) are supported.失败问题解决办法。
由于使用了NDK编译的可执行文件在应用中调用,在Android 7.0上的运行情况发现,当运行该可执行文件时,报如下错误: error: only position independent execu ...
- 【LeetCode】1471. 数组中的 k 个最强值 The k Strongest Values in an Array (Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 自定义排序 日期 题目地址:https://leetc ...
- sql注入-整数型
sql注入整数型 1.按照提示输入1,发现直接给出了SQL语句 2.使用order by判断字段数 首先使用order by 3 ,页面无回显,改为2之后页面显示正确.因此判断当前数据库当 ...
- IDEA 延长使用
压缩包下载地址:https://i.cnblogs.com/files 1.先以试用的形式进入idea,然后help -> Edit Custom VM Options 2.插入 :-javaa ...
- 论文翻译:2020_ACOUSTIC ECHO CANCELLATION WITH THE DUAL-SIGNAL TRANSFORMATION LSTM NETWORK
论文地址:https://ieeexplore.ieee.org/abstract/document/9413510 基于双信号变换LSTM网络的回声消除 摘要 本文将双信号变换LSTM网络(DTLN ...