euid, ruid, suid

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

User Identification Variables

  • ruid: Ο πραγματικός αναγνωριστικός αριθμός χρήστη δηλώνει τον χρήστη που ξεκίνησε τη διαδικασία.

  • euid: Γνωστός ως ο επιχειρησιακός αναγνωριστικός αριθμός χρήστη, αντιπροσωπεύει την ταυτότητα χρήστη που χρησιμοποιείται από το σύστημα για να προσδιορίσει τα δικαιώματα της διαδικασίας. Γενικά, το euid αντικατοπτρίζει το ruid, εκτός από περιπτώσεις όπως η εκτέλεση ενός εκτελέσιμου αρχείου SetUID, όπου το euid αναλαμβάνει την ταυτότητα του ιδιοκτήτη του αρχείου, παρέχοντας έτσι συγκεκριμένα δικαιώματα λειτουργίας.

  • suid: Αυτός ο αποθηκευμένος αναγνωριστικός αριθμός χρήστη είναι κρίσιμος όταν μια διαδικασία υψηλών δικαιωμάτων (συνήθως εκτελείται ως root) χρειάζεται προσωρινά να παραιτηθεί από τα δικαιώματά της για να εκτελέσει ορισμένες εργασίες, μόνο για να ανακτήσει αργότερα την αρχική της ανυψωμένη κατάσταση.

Important Note

Μια διαδικασία που δεν λειτουργεί υπό root μπορεί να τροποποιήσει το euid της μόνο για να ταιριάζει με το τρέχον ruid, euid ή suid.

Understanding set*uid Functions

  • setuid: Αντίθετα με τις αρχικές υποθέσεις, το setuid τροποποιεί κυρίως το euid παρά το ruid. Συγκεκριμένα, για διαδικασίες με δικαιώματα, ευθυγραμμίζει το ruid, euid και suid με τον καθορισμένο χρήστη, συχνά τον root, εδραιώνοντας αποτελεσματικά αυτούς τους αναγνωριστικούς αριθμούς λόγω του υπερκαλύπτοντος suid. Λεπτομερείς πληροφορίες μπορούν να βρεθούν στη σελίδα man του setuid.

  • setreuid και setresuid: Αυτές οι λειτουργίες επιτρέπουν την προσεκτική προσαρμογή των ruid, euid και suid. Ωστόσο, οι δυνατότητές τους εξαρτώνται από το επίπεδο δικαιωμάτων της διαδικασίας. Για διαδικασίες που δεν είναι root, οι τροποποιήσεις περιορίζονται στις τρέχουσες τιμές των ruid, euid και suid. Αντίθετα, οι διαδικασίες root ή αυτές με δυνατότητα CAP_SETUID μπορούν να αναθέσουν αυθαίρετες τιμές σε αυτούς τους αναγνωριστικούς αριθμούς. Περισσότερες πληροφορίες μπορούν να αντληθούν από τη σελίδα man του setresuid και τη σελίδα man του setreuid.

Αυτές οι λειτουργίες σχεδιάστηκαν όχι ως μηχανισμός ασφαλείας αλλά για να διευκολύνουν τη σχεδιασμένη λειτουργική ροή, όπως όταν ένα πρόγραμμα υιοθετεί την ταυτότητα ενός άλλου χρήστη αλλάζοντας τον επιχειρησιακό του αναγνωριστικό αριθμό χρήστη.

Είναι σημαντικό να σημειωθεί ότι ενώ το setuid μπορεί να είναι μια κοινή επιλογή για την ανύψωση δικαιωμάτων σε root (καθώς ευθυγραμμίζει όλους τους αναγνωριστικούς αριθμούς με τον root), η διάκριση μεταξύ αυτών των λειτουργιών είναι κρίσιμη για την κατανόηση και την παρακολούθηση των συμπεριφορών των αναγνωριστικών χρηστών σε διάφορα σενάρια.

Program Execution Mechanisms in Linux

execve System Call

  • Functionality: Το execve ξεκινά ένα πρόγραμμα, καθορισμένο από το πρώτο επιχείρημα. Δέχεται δύο πίνακες επιχειρημάτων, argv για τα επιχειρήματα και envp για το περιβάλλον.

  • Behavior: Διατηρεί τον χώρο μνήμης του καλούντος αλλά ανανεώνει τη στοίβα, το σωρό και τα τμήματα δεδομένων. Ο κώδικας του προγράμματος αντικαθίσταται από το νέο πρόγραμμα.

  • User ID Preservation:

  • ruid, euid και πρόσθετοι αναγνωριστικοί αριθμοί ομάδας παραμένουν αμετάβλητοι.

  • Το euid μπορεί να έχει λεπτές αλλαγές αν το νέο πρόγραμμα έχει οριστεί το SetUID bit.

  • Το suid ενημερώνεται από το euid μετά την εκτέλεση.

  • Documentation: Λεπτομερείς πληροφορίες μπορούν να βρεθούν στη σελίδα man του execve.

system Function

  • Functionality: Σε αντίθεση με το execve, το system δημιουργεί μια παιδική διαδικασία χρησιμοποιώντας το fork και εκτελεί μια εντολή μέσα σε αυτή την παιδική διαδικασία χρησιμοποιώντας το execl.

  • Command Execution: Εκτελεί την εντολή μέσω του sh με execl("/bin/sh", "sh", "-c", command, (char *) NULL);.

  • Behavior: Καθώς το execl είναι μια μορφή του execve, λειτουργεί παρόμοια αλλά στο πλαίσιο μιας νέας παιδικής διαδικασίας.

  • Documentation: Περισσότερες πληροφορίες μπορούν να αποκτηθούν από τη σελίδα man του system.

Behavior of bash and sh with SUID

  • bash:

  • Έχει μια επιλογή -p που επηρεάζει το πώς αντιμετωπίζονται το euid και το ruid.

  • Χωρίς -p, το bash ορίζει το euid στο ruid αν διαφέρουν αρχικά.

  • Με -p, διατηρείται το αρχικό euid.

  • Περισσότερες λεπτομέρειες μπορούν να βρεθούν στη σελίδα man του bash.

  • sh:

  • Δεν διαθέτει μηχανισμό παρόμοιο με το -p στο bash.

  • Η συμπεριφορά σχετικά με τους αναγνωριστικούς αριθμούς χρηστών δεν αναφέρεται ρητά, εκτός από την επιλογή -i, που τονίζει τη διατήρηση της ισότητας μεταξύ euid και ruid.

  • Πρόσθετες πληροφορίες είναι διαθέσιμες στη σελίδα man του sh.

Αυτοί οι μηχανισμοί, διακριτοί στη λειτουργία τους, προσφέρουν μια ευέλικτη γκάμα επιλογών για την εκτέλεση και τη μετάβαση μεταξύ προγραμμάτων, με συγκεκριμένες λεπτομέρειες σχετικά με το πώς διαχειρίζονται και διατηρούνται οι αναγνωριστικοί αριθμοί χρηστών.

Testing User ID Behaviors in Executions

Examples taken from https://0xdf.gitlab.io/2022/05/31/setuid-rabbithole.html#testing-on-jail, check it for further information

Case 1: Using setuid with system

Objective: Κατανόηση της επίδρασης του setuid σε συνδυασμό με το system και το bash ως sh.

C Code:

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>

int main(void) {
setuid(1000);
system("id");
return 0;
}

Συγκέντρωση και Άδειες:

oxdf@hacky$ gcc a.c -o /mnt/nfsshare/a;
oxdf@hacky$ chmod 4755 /mnt/nfsshare/a
bash-4.2$ $ ./a
uid=99(nobody) gid=99(nobody) groups=99(nobody) context=system_u:system_r:unconfined_service_t:s0

Ανάλυση:

  • ruid και euid ξεκινούν ως 99 (κανένας) και 1000 (frank) αντίστοιχα.

  • setuid ευθυγραμμίζει και τους δύο στο 1000.

  • system εκτελεί /bin/bash -c id λόγω του symlink από sh σε bash.

  • bash, χωρίς -p, προσαρμόζει το euid ώστε να ταιριάζει με το ruid, με αποτέλεσμα και οι δύο να είναι 99 (κανένας).

Περίπτωση 2: Χρησιμοποιώντας setreuid με system

C Κώδικας:

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>

int main(void) {
setreuid(1000, 1000);
system("id");
return 0;
}

Συγκέντρωση και Άδειες:

oxdf@hacky$ gcc b.c -o /mnt/nfsshare/b; chmod 4755 /mnt/nfsshare/b

Εκτέλεση και Αποτέλεσμα:

bash-4.2$ $ ./b
uid=1000(frank) gid=99(nobody) groups=99(nobody) context=system_u:system_r:unconfined_service_t:s0

Ανάλυση:

  • setreuid ορίζει τόσο το ruid όσο και το euid σε 1000.

  • system καλεί το bash, το οποίο διατηρεί τα αναγνωριστικά χρηστών λόγω της ισότητας τους, λειτουργώντας αποτελεσματικά ως frank.

Περίπτωση 3: Χρήση setuid με execve

Στόχος: Εξερεύνηση της αλληλεπίδρασης μεταξύ setuid και execve.

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>

int main(void) {
setuid(1000);
execve("/usr/bin/id", NULL, NULL);
return 0;
}

Εκτέλεση και Αποτέλεσμα:

bash-4.2$ $ ./c
uid=99(nobody) gid=99(nobody) euid=1000(frank) groups=99(nobody) context=system_u:system_r:unconfined_service_t:s0

Ανάλυση:

  • ruid παραμένει 99, αλλά το euid έχει οριστεί σε 1000, σύμφωνα με την επίδραση του setuid.

C Code Example 2 (Calling Bash):

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>

int main(void) {
setuid(1000);
execve("/bin/bash", NULL, NULL);
return 0;
}

Εκτέλεση και Αποτέλεσμα:

bash-4.2$ $ ./d
bash-4.2$ $ id
uid=99(nobody) gid=99(nobody) groups=99(nobody) context=system_u:system_r:unconfined_service_t:s0

Ανάλυση:

  • Αν και το euid έχει οριστεί σε 1000 από το setuid, το bash επαναφέρει το euid σε ruid (99) λόγω της απουσίας του -p.

C Code Example 3 (Using bash -p):

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>

int main(void) {
char *const paramList[10] = {"/bin/bash", "-p", NULL};
setuid(1000);
execve(paramList[0], paramList, NULL);
return 0;
}

Εκτέλεση και Αποτέλεσμα:

bash-4.2$ $ ./e
bash-4.2$ $ id
uid=99(nobody) gid=99(nobody) euid=100

Αναφορές

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

Υποστήριξη HackTricks

Last updated