DDexec / EverythingExec

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

Πλαίσιο

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

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

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

Εξαρτήσεις

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

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.

Τώρα, έχουμε τέσσερα βασικά προβλήματα που πρέπει να αντιμετωπίσουμε:

  • Γενικά, μόνο ο ριζικός χρήστης και ο ιδιοκτήτης του προγράμματος μπορούν να το τροποποιήσουν.

  • ASLR.

  • Εάν προσπαθήσουμε να διαβάσουμε ή να γράψουμε σε μια διεύθυνση που δεν έχει αντιστοιχιστεί στον χώρο διεύθυνσης του προγράμματος, θα λάβουμε σφάλμα εισόδου/εξόδου.

Αυτά τα προβλήματα έχουν λύσεις που, αν και δεν είναι τέλειες, είναι καλές:

  • Τα περισσότερα διερμηνευτές κελύφους επιτρέπουν τη δημιουργία περιγραφέων αρχείων που στη συνέχεια θα κληρονομηθούν από διεργασίες-παιδιά. Μπορούμε να δημιουργήσουμε έναν περιγραφέα που δείχνει στο αρχείο mem του κελύφους με δικαιώματα εγγραφής... έτσι οι διεργασίες-παιδιά που χρησιμοποιούν αυτόν τον περιγραφέα θα μπορούν να τροποποιήσουν τη μνήμη του κελύφους.

  • Το ASLR δεν είναι καν πρόβλημα, μπορούμε να ελέγξουμε το αρχείο maps του κελύφους ή οποιοδήποτε άλλο από το procfs για να αποκτήσουμε πληροφορίες σχετικά με τον χώρο διεύθυνσης της διεργασίας.

  • Έτσι χρειάζεται να κάνουμε lseek() στο αρχείο. Από το κελύφους αυτό δεν μπορεί να γίνει εκτός αν χρησιμοποιήσουμε τον περίφημο dd.

Λεπτομερειακά

Τα βήματα είναι σχετικά εύκολα και δεν απαιτούν καμία ειδική εμπειρία για να τα κατανοήσετε:

  • Αναλύστε το δυαδικό που θέλουμε να εκτελέσουμε και τον φορτωτή για να βρούμε ποιες αντιστοιχίσεις χρειάζονται. Στη συνέχεια δημιουργήστε ένα "shell"code που θα εκτελέσει, γενικά μιλώντας, τα ίδια βήματα που κάνει το πυρήνας κάθε φορά που καλείται η execve():

  • Δημιουργήστε τις εν λόγω αντιστοιχίσεις.

  • Διαβάστε τα δυαδικά σε αυτές.

  • Διαμορφώστε τα δικαιώματα.

  • Τέλος, αρχικοποιήστε τη στοίβα με τα ορίσματα για το πρόγραμμα και τοποθετήστε τον βοηθητικό διάνυσμα (απαραίτητο από τον φορτωτή).

  • Μπείτε στον φορτωτή και αφήστε τον να κάνει τα υπόλοιπα (φόρτωση βιβλιοθηκών που χρειάζεται το πρόγραμμα).

  • Αποκτήστε από το αρχείο syscall τη διεύθυνση στην οποία θα επιστρέψει η διεργασία μετά την κλήση συστήματος που εκτελεί.

  • Αντικαταστήστε αυτό το σημείο, το οποίο θα είναι εκτελέσιμο, με το shellcode μας (μέσω του mem μπορούμε να τροποποιήσουμε σελίδες που δεν είναι εγγράψιμες).

  • Περάστε το πρόγραμμα που θέλουμε να εκτελέσουμε στην είσοδο της διεργασίας (θα το διαβάσει το εν λόγω "shell"code).

  • Σε αυτό το σημείο είναι υπό τον φορτωτή να φορτώσει τις απαραίτητες βιβλιοθήκες για το πρόγραμμά μας και να μπει σε αυτό.

Ελέγξτε το εργαλείο στο https://github.com/arget13/DDexec

EverythingExec

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

tail
hexdump
cmp
xxd

Με την ρύθμιση της μεταβλητής SEEKER μπορείτε να αλλάξετε τον ψάχτη που χρησιμοποιείται, π.χ.:

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

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

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

Φράξτε αυτό, EDRs.

Αναφορές

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

Last updated