DDexec / EverythingExec

Reading time: 6 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Context

Στο Linux, για να εκτελέσετε ένα πρόγραμμα, πρέπει να υπάρχει ως αρχείο, πρέπει να είναι προσβάσιμο με κάποιο τρόπο μέσω της ιεραρχίας του συστήματος αρχείων (αυτός είναι ο τρόπος που λειτουργεί το execve()). Αυτό το αρχείο μπορεί να βρίσκεται σε δίσκο ή σε ram (tmpfs, memfd) αλλά χρειάζεστε μια διαδρομή αρχείου. Αυτό έχει διευκολύνει πολύ τον έλεγχο του τι εκτελείται σε ένα σύστημα Linux, διευκολύνει την ανίχνευση απειλών και εργαλείων επιτιθέμενων ή την αποτροπή τους από το να προσπαθήσουν να εκτελέσουν οτιδήποτε δικό τους (π.χ. να μην επιτρέπεται στους μη προνομιούχους χρήστες να τοποθετούν εκτελέσιμα αρχεία οπουδήποτε).

Αλλά αυτή η τεχνική είναι εδώ για να αλλάξει όλα αυτά. Αν δεν μπορείτε να ξεκινήσετε τη διαδικασία που θέλετε... τότε καταλαμβάνετε μία που ήδη υπάρχει.

Αυτή η τεχνική σας επιτρέπει να παρακάμψετε κοινές τεχνικές προστασίας όπως read-only, noexec, whitelist ονομάτων αρχείων, whitelist hash...

Dependencies

Το τελικό σενάριο εξαρτάται από τα παρακάτω εργαλεία για να λειτουργήσει, πρέπει να είναι προσβάσιμα στο σύστημα που επιτίθεστε (κατά προεπιλογή θα τα βρείτε παντού):

dd
bash | zsh | ash (busybox)
head
tail
cut
grep
od
readlink
wc
tr
base64

Η τεχνική

Αν μπορείτε να τροποποιήσετε αυθαίρετα τη μνήμη μιας διαδικασίας, τότε μπορείτε να την αναλάβετε. Αυτό μπορεί να χρησιμοποιηθεί για να καταλάβετε μια ήδη υπάρχουσα διαδικασία και να την αντικαταστήσετε με ένα άλλο πρόγραμμα. Μπορούμε να το πετύχουμε είτε χρησιμοποιώντας την κλήση συστήματος 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

EverythingExec

Υπάρχουν αρκετές εναλλακτικές στο dd, μία από τις οποίες, το tail, είναι αυτή τη στιγμή το προεπιλεγμένο πρόγραμμα που χρησιμοποιείται για να lseek() μέσω του αρχείου mem (το οποίο ήταν ο μοναδικός σκοπός για τη χρήση του dd). Οι εν λόγω εναλλακτικές είναι:

bash
tail
hexdump
cmp
xxd

Ορίζοντας τη μεταβλητή SEEKER μπορείτε να αλλάξετε τον ανακριτή που χρησιμοποιείται, π.χ.:

bash
SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Αν βρείτε έναν άλλο έγκυρο seeker που δεν έχει υλοποιηθεί στο σενάριο, μπορείτε να τον χρησιμοποιήσετε ρυθμίζοντας τη μεταβλητή SEEKER_ARGS:

bash
SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Αποκλείστε αυτό, EDRs.

Αναφορές

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks