一、模板注入与常见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模板引擎为例)的更多相关文章

  1. opencart 引入 TWIG 模板引擎

     1.首先将 twig 包放入 system\library 目录. 2.在 system/startup.php 文件最后添加引入语句. require_once(DIR_SYSTEM . 'lib ...

  2. 构建自己的PHP框架(Twig模板引擎)

    完整项目地址:https://github.com/Evai/Aier Twig 模板引擎 模版引擎 twig 的模板就是普通的文本文件,也不需要特别的扩展名,.html .htm .twig 都可以 ...

  3. 原生twig模板引擎详解(安装使用)

    最近在学习SSTI(服务器模板注入),所以在此总结一下 0x00 Twig的介绍 什么是Twig? Twig是一款灵活.快速.安全的PHP模板引擎. Twig的特点? 快速:Twig将模板编译为纯粹的 ...

  4. yii2 使用twig 模板引擎

    yii2 默认使用PHP 和html 混合的方式来写视图层,但我个人还是喜欢纯模板语言的方式.而且已经非常习惯使用twig的语法,最近想使用yii2进行开发,所以还是选择使用twig视图引擎. git ...

  5. twig 模板引擎使渲染视图更加优雅

    在使用 laravel 的时候接触过 blade 模板引擎.在学习的时候,接触到了另外一个强大的模板引擎:twig 官网:https://twig.sensiolabs.org/ 中文手册:http: ...

  6. symfony2 twig模板引擎

    1.基本语法 Says something:{{    }} Does something:{%  %} Comment something:{#    #} {% extends "App ...

  7. laravel Blade 模板引擎

    与视图文件紧密关联的就是模板代码,我们在视图文件中通过模板代码和 HTML 代码结合实现视图的渲染.和很多其他后端语言不同,PHP 本身就可以当做模板语言来使用,但是这种方式有很多缺点,比如安全上的隐 ...

  8. 第115天:Ajax 中artTemplate模板引擎(一)

    一.不分离与分离的比较 1.前后端不分离,以freemarker模板引擎为例,看一下不分离的前后端请求的流程是什么样的? 从上图可以看出,前后端开发人员的工作耦合主要在(3)Template的使用.后 ...

  9. thinkphp5.1 - twig模板-全局变量

    thinkphp5.1 - twig模板-全局变量我们在定义 ccs 之类的静态文件的时候,经常会使用<link rel="stylesheet" href="__ ...

随机推荐

  1. 转:苹果iphone APP界面设计尺寸官方版

    苹果iphone APP界面设计尺寸官方版

  2. Table.RenameColumns重命名…Rename…(Power Query 之 M 语言)

    数据源: "姓名""基数"等列 目标: 修改"姓名"列标题为"员工姓名" 操作过程: [转换]>[重命名]> ...

  3. 解放生产力「GitHub 热点速览 v.21.51」

    作者:HelloGitHub-小鱼干 解放生产力一直都是我们共同追求的目标,能在摸鱼的空闲把赚了.而大部分好用的工具便能很好地解放我们的生产力,比如本周特推 RedisJSON 不用对 JSON 做哈 ...

  4. Python第三周 数据类型:集合set、文件的读写、追加操作。

    集合 知识点:集合是无序的 格式:{1,2,3,"str_test"} set_1 = set(list1)#将列表转换为集合 集合关系测试: 集合的逻辑判断.取交集.并集.差集. ...

  5. react 结合antd 实现分页效果

    import React, { useState, useEffect } from "react"; // antd import { Pagination } from &qu ...

  6. 深入理解Akka Actor模型

    Carl Hewitt 在1973年对Actor模型进行了如下定义:"Actor模型是一个把'Actor'作为并发计算的通用原语". Actor是异步驱动,可以并行和分布式部署及运 ...

  7. Linux下c++之常见错误代码errno(退而结网法)

    1.关于 还在到处找 errno对应的含义? 自己动手,很方便可找到其明确的含义 2. 动手 2.1 创建 c++源文件,输入下面的代码: #pragma once #include <iost ...

  8. 【LeetCode】748. Shortest Completing Word 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  9. 【剑指Offer】旋转数组中的最小数字 解题报告(Python)

    [剑指Offer]旋转数组中的最小数字 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

  10. Fibonacci String(hdu 1708)

    Fibonacci String Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...