English · Ελληνικά
Enter-PSSession πάνω από CredSSP. Εγώ το έκανα ολόκληρο από ένα Mac με Apple silicon. Το μονοπάτι είναι μια καθαρή αλυσίδα credentials με τέσσερα άλματα: ένα ανώνυμο SMB share παραδίδει ένα custom UserInfo.exe· η αποσυμπίληση του αποκαλύπτει έναν hardcoded κωδικό LDAP κρυμμένο πίσω από μια τετριμμένη ρουτίνα XOR· αυτός ο read-only λογαριασμός LDAP βρίσκει άλλον κωδικό μέσα στο attribute info του χρήστη support, ο οποίος είναι μέλος των Remote Management Users για WinRM foothold· και τέλος η συμμετοχή του support σε μια ομάδα με GenericAll πάνω στον domain controller οδηγεί μια αλυσίδα Resource-Based Constrained Delegation μέχρι το Domain Admin. Κάθε βήμα έτρεξε πάνω σε εργαλεία macOS/Linux — ilspycmd, ldapsearch, evil-winrm και pure-Python impacket.
Ένα πλήρες σάρωμα TCP είναι σχολικό παράδειγμα domain controller — DNS, Kerberos, LDAP, το global catalog, SMB, WinRM και ADWS. Domain support.htb, hostname DC, Windows Server 2022. Αξίζει να σημειωθεί νωρίς: η ώρα του server Kerberos στο port 88 ταίριαζε με το ρολόι του host μου, οπότε δεν χρειάστηκε καθόλου το μπερδεμα με faketime που απαιτούν κάποια boxes AD.
Προσθέτουμε τον DC στο /etc/hosts εξαρχής — το Kerberos κάνει resolve τα service principal μέσω hostname, και το βήμα RBCD στο τέλος κάνει authenticate πάνω στο dc.support.htb, όχι σε μια IP:
Ένα null session κάνει authenticate αλλά δεν μπορεί να λίστάρει shares. Ένα login guest — οποιοδήποτε username, κενός κωδικός — μπορεί, και αυτή η διάκριση έχει σημασία: null και guest είναι διαφορετικά μονοπάτια auth, και τα boxes συχνά μπλοκάρουν το ένα αφήνοντας το άλλο ανοιχτό.
Το support-tools είναι αναγνώσιμο. Το μεγαλύτερο μέρος του περιεχομένου του είναι έτοιμες portable εφαρμογές (7-Zip, Notepad++, PuTTY, Sysinternals, Wireshark) — αλλά ένα αρχείο δεν ταιριάζει: ένα custom UserInfo.exe.zip. Εσωτερικά εργαλεία που κατέληξαν σε ένα ανοιχτό share είναι ακριβώς εκεί που ζουν τα hardcoded credentials.
Το dnSpy είναι μόνο για Windows, αλλά ένα .NET assembly αποσυμπιλείται καθαρά σε macOS με το cross-platform εργαλείο γραμμής εντολών ILSpy. Εγκαθίσταται ως global tool του dotnet. Μια παγίδα με το Homebrew dotnet: το ilspycmd δεν βρίσκει το runtime εκτός αν το DOTNET_ROOT δείχνει στον φάκελο libexec (όχι στο bin).
Κάνοντας grep στον αποσυμπιλημένο κώδικα ανάβει αμέσως. Υπάρχει ένα hardcoded username, ένας base64 «κρυπτογραφημένος» κωδικός, και μια getPassword() που τον «αποκρυπτογραφεί»:
Η «κρυπτογράφηση» είναι base64 και μετά ένα byte-wise XOR έναντι του επαναλαμβανόμενου κλειδιού armando, ξανά XOR με τη σταθερά 0xDF. Το XOR είναι συμμετρικό, οπότε «αποκρυπτογράφηση» είναι απλά να τρέξεις την ίδια ρουτίνα που μας έδωσε ήδη ο κώδικας. Τρεις γραμμές Python ανακτούν τον κωδικό:
Οπότε έχουμε τον support\ldap και τον κωδικό του σε cleartext — έναν λογαριασμό χαμηλών προνομίων, αλλά αρκετό για να διαβάσουμε τον directory.
Το binary έκανε queries χρηστών LDAP, οπότε η φυσική επόμενη κίνηση είναι να κάνουμε enumerate τα user objects και να ψάξουμε κάτι σε ένα πεδίο που σπάνια επιθεωρείται. Το attribute info (το κουτί «Notes» στο ADUC) είναι κλασικός τόπος απόρριψης για admins που νομίζουν ότι είναι σκοτεινό. Φιλτράροντας για τον λογαριασμό support αποδίδει αμέσως:
Δύο δώρα σε ένα query: ένας υποψήφιος κωδικός για τον λογαριασμό support, και επιβεβαίωση ότι ο support είναι στα Remote Management Users (πρόσβαση WinRM) και στα Shared Support Accounts — η ομάδα που θα εκμεταλλευτούμε για privesc.
Η τιμή του info είναι έγκυρο credential, και το Remote Management Users σημαίνει ότι δουλεύει πάνω από WinRM:
Το BloodHound (ή απλά διαβάζοντας το ACL της ομάδας) δείχνει ότι τα Shared Support Accounts — στα οποία ανήκει ο support — έχουν GenericAll πάνω στο computer object του domain controller, DC$. Αυτό το write primitive είναι όλο το παιχνίδι: αν μπορώ να θέσω το msDS-AllowedToActOnBehalfOfOtherIdentity στο DC$ σε ένα principal που ελέγχω, μπορώ να χρησιμοποιήσω S4U για να κάνω impersonate οποιονδήποτε χρήστη — Domain Admin συμπεριλαμβανομένου — προς υπηρεσίες στον DC. Αυτό είναι RBCD, και τρέχει από άκρη σε άκρη από Linux/macOS με impacket.
Πρώτα επιβεβαιώνουμε ότι το machine-account quota επιτρέπει τη δημιουργία ενός computer (default 10), μετά δημιουργούμε ένα για να είναι το delegate-from principal:
Γράφουμε το attribute RBCD στο DC$ ώστε να εμπιστεύεται το ATTACK$ να ενεργεί εκ μέρους άλλων:
Τώρα S4U2Self+S4U2Proxy ως ATTACK$ για να κόψουμε ένα service ticket cifs/dc.support.htb ως ο Administrator:
Δείχνουμε το KRB5CCNAME στο ccache και εκτελούμε ως SYSTEM. Εδώ είναι που η εγγραφή στο /etc/hosts δικαιολογεί την ύπαρξή της — το Kerberos κάνει authenticate έναντι του hostname SPN, οπότε ο στόχος πρέπει να είναι dc.support.htb, ποτέ μια IP:
psexec.py έσπασε κάτω από Python 3.14 (STATUS_PIPE_BROKEN) παρόλο που η υπηρεσία SYSTEM ξεκίνησε κανονικά. Το wmiexec.py περνάει μία εντολή καθαρά και ήταν το πιο αξιόπιστο one-shot για να διαβάσουμε το flag. Και κάνε cleanup μετά τον εαυτό σου σε πραγματικό engagement: ο λογαριασμός ATTACK$ και το attribute RBCD στο DC$ παραμένουν και τα δύο στο domain (rbcd.py -action flush, μετά διαγραφή του computer object).| Στάδιο | Ριζική αιτία |
|---|---|
| → support-tools | Ανώνυμη/guest ανάγνωση SMB σε ένα share που κρατάει εσωτερικά εργαλεία (CWE-284 — ακατάλληλος έλεγχος πρόσβασης) |
| → ldap creds | Hardcoded credential συσκοτισμένο με αντιστρέψιμο XOR + κλειδί που στάλθηκε μαζί του — obfuscation, όχι κρυπτογράφηση (CWE-798 / CWE-312) |
| → support (WinRM) | Κωδικός σε cleartext αποθηκευμένος στο attribute info του λογαριασμού, αναγνώσιμος από κάθε authenticated principal (CWE-522) |
| → Domain Admin | Μια ομάδα support κρατάει GenericAll πάνω στο DC object → εγγραφή msDS-AllowedToActOnBehalfOfOtherIdentity → RBCD (CWE-266 — over-privileged ACL) |
ilspycmd αντικαθιστά το dnSpy για αποσυμπίληση .NET, και ολόκληρη η αλυσίδα RBCD (addcomputer.py → rbcd.py → getST.py → wmiexec.py) αναπαράγει τη ροή εργασίας PowerView/Powermad/Rubeus σε pure-Python impacket — που επίσης παρακάμπτει τον χορό CredSSP που χρειάζεται ένα μη-domain-joined Windows box για WinRM.faketime εδώ· αν δεν ταίριαζε, το bloodyAD διορθώνει αυτόματα την απόκλιση και το NTLM (-H) παρακάμπτει εντελώς το Kerberos.DOTNET_ROOT σε Homebrew. Δείξε το στο .../Cellar/dotnet/<ver>/libexec, όχι στο bin, αλλιώς το ilspycmd αναφέρει το runtime ως «not found».