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.

  • 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 (nobody) та 1000 (frank) відповідно.

  • setuid вирівнює обидва до 1000.

  • system виконує /bin/bash -c id через symlink від sh до bash.

  • bash, без -p, коригує euid, щоб відповідати ruid, в результаті чого обидва стають 99 (nobody).

Випадок 2: Використання setreuid з system

C Code:

#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 Код Приклад 2 (Виклик 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 Код Приклад 3 (Використовуючи 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