DDexec / EverythingExec
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Στο Linux, για να εκτελέσετε ένα πρόγραμμα, πρέπει να υπάρχει ως αρχείο, πρέπει να είναι προσβάσιμο με κάποιο τρόπο μέσω της ιεραρχίας του συστήματος αρχείων (αυτός είναι ο τρόπος που λειτουργεί το execve()
). Αυτό το αρχείο μπορεί να βρίσκεται στον δίσκο ή στη μνήμη (tmpfs, memfd) αλλά χρειάζεστε μια διαδρομή αρχείου. Αυτό έχει διευκολύνει πολύ τον έλεγχο του τι εκτελείται σε ένα σύστημα Linux, διευκολύνει την ανίχνευση απειλών και εργαλείων επιτιθέμενων ή την πρόληψη της εκτέλεσης οτιδήποτε δικό τους (π.χ. να μην επιτρέπεται στους μη προνομιούχους χρήστες να τοποθετούν εκτελέσιμα αρχεία οπουδήποτε).
Αλλά αυτή η τεχνική είναι εδώ για να αλλάξει όλα αυτά. Αν δεν μπορείτε να ξεκινήσετε τη διαδικασία που θέλετε... τότε καταλαμβάνετε μία που ήδη υπάρχει.
Αυτή η τεχνική σας επιτρέπει να παρακάμψετε κοινές τεχνικές προστασίας όπως read-only, noexec, λευκή λίστα ονομάτων αρχείων, λευκή λίστα hash...
Το τελικό σενάριο εξαρτάται από τα παρακάτω εργαλεία για να λειτουργήσει, πρέπει να είναι προσβάσιμα στο σύστημα που επιτίθεστε (κατά προεπιλογή θα τα βρείτε παντού):
Εάν μπορείτε να τροποποιήσετε αυθαίρετα τη μνήμη μιας διαδικασίας, τότε μπορείτε να την αναλάβετε. Αυτό μπορεί να χρησιμοποιηθεί για να καταλάβετε μια ήδη υπάρχουσα διαδικασία και να την αντικαταστήσετε με ένα άλλο πρόγραμμα. Μπορούμε να το πετύχουμε είτε χρησιμοποιώντας την κλήση συστήματος ptrace()
(η οποία απαιτεί να έχετε τη δυνατότητα να εκτελείτε κλήσεις συστήματος ή να έχετε το gdb διαθέσιμο στο σύστημα) είτε, πιο ενδιαφέροντα, γράφοντας στο /proc/$pid/mem
.
Το αρχείο /proc/$pid/mem
είναι μια μία προς μία αντιστοίχιση ολόκληρου του χώρου διευθύνσεων μιας διαδικασίας (π.χ. από 0x0000000000000000
έως 0x7ffffffffffff000
σε x86-64). Αυτό σημαίνει ότι η ανάγνωση ή η εγγραφή σε αυτό το αρχείο σε μια μετατόπιση x
είναι το ίδιο με την ανάγνωση ή την τροποποίηση του περιεχομένου στη εικονική διεύθυνση x
.
Τώρα, έχουμε τέσσερα βασικά προβλήματα να αντιμετωπίσουμε:
Γενικά, μόνο ο root και ο ιδιοκτήτης του προγράμματος του αρχείου μπορεί να το τροποποιήσει.
ASLR.
Εάν προσπαθήσουμε να διαβάσουμε ή να γράψουμε σε μια διεύθυνση που δεν είναι χαρτογραφημένη στο χώρο διευθύνσεων του προγράμματος, θα λάβουμε ένα σφάλμα I/O.
Αυτά τα προβλήματα έχουν λύσεις που, αν και δεν είναι τέλειες, είναι καλές:
Οι περισσότερες ερμηνευτές κελύφους επιτρέπουν τη δημιουργία περιγραφικών αρχείων που θα κληρονομηθούν από τις παιδικές διαδικασίες. Μπορούμε να δημιουργήσουμε ένα fd που να δείχνει στο αρχείο mem
του κελύφους με δικαιώματα εγγραφής... έτσι οι παιδικές διαδικασίες που χρησιμοποιούν αυτό το fd θα μπορούν να τροποποιήσουν τη μνήμη του κελύφους.
Το ASLR δεν είναι καν πρόβλημα, μπορούμε να ελέγξουμε το αρχείο maps
του κελύφους ή οποιοδήποτε άλλο από το procfs προκειμένου να αποκτήσουμε πληροφορίες σχετικά με το χώρο διευθύνσεων της διαδικασίας.
Έτσι, πρέπει να κάνουμε lseek()
πάνω από το αρχείο. Από το κέλυφος αυτό δεν μπορεί να γίνει εκτός αν χρησιμοποιήσουμε το α infamous dd
.
Τα βήματα είναι σχετικά εύκολα και δεν απαιτούν καμία ειδική γνώση για να τα κατανοήσετε:
Αναλύστε το δυαδικό αρχείο που θέλουμε να εκτελέσουμε και τον φορτωτή για να ανακαλύψουμε ποιες αντιστοιχίσεις χρειάζονται. Στη συνέχεια, δημιουργήστε έναν "κώδικα" κελύφους που θα εκτελεί, γενικά μιλώντας, τα ίδια βήματα που εκτελεί ο πυρήνας σε κάθε κλήση προς το execve()
:
Δημιουργήστε τις εν λόγω αντιστοιχίσεις.
Διαβάστε τα δυαδικά αρχεία σε αυτές.
Ρυθμίστε τα δικαιώματα.
Τέλος, αρχικοποιήστε τη στοίβα με τα επιχειρήματα για το πρόγραμμα και τοποθετήστε το βοηθητικό διάνυσμα (που απαιτείται από τον φορτωτή).
Πηδήξτε στον φορτωτή και αφήστε τον να κάνει τα υπόλοιπα (να φορτώσει τις βιβλιοθήκες που απαιτούνται από το πρόγραμμα).
Αποκτήστε από το αρχείο syscall
τη διεύθυνση στην οποία θα επιστρέψει η διαδικασία μετά την κλήση συστήματος που εκτελεί.
Επικαλύψτε αυτό το σημείο, το οποίο θα είναι εκτελέσιμο, με τον κώδικα κελύφους μας (μέσω του mem
μπορούμε να τροποποιήσουμε μη εγγράψιμες σελίδες).
Περάστε το πρόγραμμα που θέλουμε να εκτελέσουμε στο stdin της διαδικασίας (θα διαβαστεί από τον εν λόγω "κώδικα" κελύφους).
Σε αυτό το σημείο, είναι στο χέρι του φορτωτή να φορτώσει τις απαραίτητες βιβλιοθήκες για το πρόγραμμα μας και να πηδήξει σε αυτό.
Δείτε το εργαλείο στο https://github.com/arget13/DDexec
Υπάρχουν αρκετές εναλλακτικές λύσεις στο dd
, μία από τις οποίες, το tail
, είναι αυτή τη στιγμή το προεπιλεγμένο πρόγραμμα που χρησιμοποιείται για να lseek()
μέσω του αρχείου mem
(το οποίο ήταν ο μοναδικός σκοπός για τη χρήση του dd
). Οι εν λόγω εναλλακτικές είναι:
Ορίζοντας τη μεταβλητή SEEKER
μπορείτε να αλλάξετε τον ανακριτή που χρησιμοποιείται, π.χ.:
Αν βρείτε έναν άλλο έγκυρο seeker που δεν έχει υλοποιηθεί στο σενάριο, μπορείτε να τον χρησιμοποιήσετε ρυθμίζοντας τη μεταβλητή SEEKER_ARGS
:
Block this, EDRs.
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)