hacktricks/linux-hardening/privilege-escalation/euid-ruid-suid.md

10 KiB

euid, ruid, suid

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Variabili di Identificazione Utente

  • ruid: Il real user ID indica l'utente che ha avviato il processo.
  • euid: Conosciuto come effective user ID, rappresenta l'identità utente utilizzata dal sistema per determinare i privilegi del processo. Generalmente, euid rispecchia ruid, tranne in casi come l'esecuzione di un binario SetUID, dove euid assume l'identità del proprietario del file, concedendo così specifici permessi operativi.
  • suid: Questo saved user ID è fondamentale quando un processo ad alto privilegio (tipicamente in esecuzione come root) deve temporaneamente rinunciare ai propri privilegi per eseguire determinate operazioni, per poi riacquistare il proprio stato elevato iniziale.

Nota Importante

Un processo che non opera sotto root può modificare il proprio euid solo per farlo corrispondere all'attuale ruid, euid o suid.

Comprendere le Funzioni set*uid

  • setuid: Contrariamente alle assunzioni iniziali, setuid modifica principalmente euid piuttosto che ruid. Specificamente, per i processi privilegiati, allinea ruid, euid e suid con l'utente specificato, spesso root, consolidando efficacemente questi ID a causa del suid sovrascritto. Informazioni dettagliate possono essere trovate nella pagina man di setuid.
  • setreuid e setresuid: Queste funzioni consentono la regolazione sfumata di ruid, euid e suid. Tuttavia, le loro capacità dipendono dal livello di privilegio del processo. Per i processi non root, le modifiche sono limitate ai valori attuali di ruid, euid e suid. Al contrario, i processi root o quelli con la capacità CAP_SETUID possono assegnare valori arbitrari a questi ID. Maggiori informazioni possono essere ottenute dalla pagina man di setresuid e dalla pagina man di setreuid.

Queste funzionalità non sono progettate come un meccanismo di sicurezza, ma per facilitare il flusso operativo previsto, come quando un programma adotta l'identità di un altro utente modificando il proprio effective user ID.

È importante notare che, mentre setuid potrebbe essere una scelta comune per l'elevazione dei privilegi a root (poiché allinea tutti gli ID a root), differenziare tra queste funzioni è cruciale per comprendere e manipolare i comportamenti degli ID utente in vari scenari.

Meccanismi di Esecuzione dei Programmi in Linux

Chiamata di Sistema execve

  • Funzionalità: execve avvia un programma, determinato dal primo argomento. Prende due argomenti array, argv per gli argomenti e envp per l'ambiente.
  • Comportamento: Mantiene lo spazio di memoria del chiamante ma aggiorna lo stack, l'heap e i segmenti di dati. Il codice del programma viene sostituito dal nuovo programma.
  • Preservazione dell'ID Utente:
  • ruid, euid e gli ID di gruppo supplementari rimangono invariati.
  • euid potrebbe subire modifiche sfumate se il nuovo programma ha impostato il bit SetUID.
  • suid viene aggiornato da euid dopo l'esecuzione.
  • Documentazione: Informazioni dettagliate possono essere trovate nella pagina man di execve.

Funzione system

  • Funzionalità: A differenza di execve, system crea un processo figlio utilizzando fork ed esegue un comando all'interno di quel processo figlio utilizzando execl.
  • Esecuzione del Comando: Esegue il comando tramite sh con execl("/bin/sh", "sh", "-c", command, (char *) NULL);.
  • Comportamento: Poiché execl è una forma di execve, opera in modo simile ma nel contesto di un nuovo processo figlio.
  • Documentazione: Ulteriori informazioni possono essere ottenute dalla pagina man di system.

Comportamento di bash e sh con SUID

  • bash:
  • Ha un'opzione -p che influisce su come vengono trattati euid e ruid.
  • Senza -p, bash imposta euid su ruid se inizialmente differiscono.
  • Con -p, l'iniziale euid viene preservato.
  • Maggiori dettagli possono essere trovati nella pagina man di bash.
  • sh:
  • Non possiede un meccanismo simile a -p in bash.
  • Il comportamento riguardante gli ID utente non è esplicitamente menzionato, tranne che sotto l'opzione -i, enfatizzando la preservazione dell'uguaglianza tra euid e ruid.
  • Ulteriori informazioni sono disponibili sulla pagina man di sh.

Questi meccanismi, distinti nel loro funzionamento, offrono una gamma versatile di opzioni per eseguire e passare tra programmi, con specifiche sfumature su come vengono gestiti e preservati gli ID utente.

Testare i Comportamenti degli ID Utente nelle Esecuzioni

Esempi tratti da https://0xdf.gitlab.io/2022/05/31/setuid-rabbithole.html#testing-on-jail, controlla per ulteriori informazioni

Caso 1: Utilizzare setuid con system

Obiettivo: Comprendere l'effetto di setuid in combinazione con system e bash come sh.

Codice C:

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

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

Compilazione e Permessi:

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

Analisi:

  • ruid ed euid iniziano come 99 (nobody) e 1000 (frank) rispettivamente.
  • setuid allinea entrambi a 1000.
  • system esegue /bin/bash -c id a causa del symlink da sh a bash.
  • bash, senza -p, regola euid per corrispondere a ruid, risultando in entrambi che sono 99 (nobody).

Caso 2: Utilizzando setreuid con system

Codice C:

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

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

Compilazione e Permessi:

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

Esecuzione e Risultato:

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

Analisi:

  • setreuid imposta sia ruid che euid a 1000.
  • system invoca bash, che mantiene gli ID utente a causa della loro uguaglianza, operando effettivamente come frank.

Caso 3: Utilizzo di setuid con execve

Obiettivo: Esplorare l'interazione tra setuid ed execve.

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

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

Esecuzione e Risultato:

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

Analisi:

  • ruid rimane 99, ma euid è impostato su 1000, in linea con l'effetto di setuid.

Esempio di codice C 2 (Chiamando Bash):

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

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

Esecuzione e Risultato:

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

Analisi:

  • Anche se euid è impostato a 1000 da setuid, bash ripristina euid a ruid (99) a causa dell'assenza di -p.

Esempio di codice C 3 (Utilizzando 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;
}

Esecuzione e Risultato:

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

Riferimenti

{% hint style="success" %} Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks
{% endhint %}