{% 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
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
ruid
: The real user ID denotes the user who initiated the process.euid
: Known as the effective user ID, it represents the user identity utilized by the system to ascertain process privileges. Generally,euid
mirrorsruid
, barring instances like a SetUID binary execution, whereeuid
assumes the file owner's identity, thus granting specific operational permissions.suid
: This saved user ID is pivotal when a high-privilege process (typically running as root) needs to temporarily relinquish its privileges to perform certain tasks, only to later reclaim its initial elevated status.
A process not operating under root can only modify its euid
to match the current ruid
, euid
, or suid
.
setuid
: Contrary to initial assumptions,setuid
primarily modifieseuid
rather thanruid
. Specifically, for privileged processes, it alignsruid
,euid
, andsuid
with the specified user, often root, effectively solidifying these IDs due to the overridingsuid
. Detailed insights can be found in the setuid man page.setreuid
andsetresuid
: These functions allow for the nuanced adjustment ofruid
,euid
, andsuid
. However, their capabilities are contingent on the process's privilege level. For non-root processes, modifications are restricted to the current values ofruid
,euid
, andsuid
. In contrast, root processes or those withCAP_SETUID
capability can assign arbitrary values to these IDs. More information can be gleaned from the setresuid man page and the setreuid man page.
These functionalities are designed not as a security mechanism but to facilitate the intended operational flow, such as when a program adopts another user's identity by altering its effective user ID.
Notably, while setuid
might be a common go-to for privilege elevation to root (since it aligns all IDs to root), differentiating between these functions is crucial for understanding and manipulating user ID behaviors in varying scenarios.
- Functionality:
execve
initiates a program, determined by the first argument. It takes two array arguments,argv
for arguments andenvp
for the environment. - Behavior: It retains the memory space of the caller but refreshes the stack, heap, and data segments. The program's code is replaced by the new program.
- User ID Preservation:
ruid
,euid
, and supplementary group IDs remain unaltered.euid
might have nuanced changes if the new program has the SetUID bit set.suid
gets updated fromeuid
post-execution.
- Documentation: Detailed information can be found on the
execve
man page.
- Functionality: Unlike
execve
,system
creates a child process usingfork
and executes a command within that child process usingexecl
. - Command Execution: Executes the command via
sh
withexecl("/bin/sh", "sh", "-c", command, (char *) NULL);
. - Behavior: As
execl
is a form ofexecve
, it operates similarly but in the context of a new child process. - Documentation: Further insights can be obtained from the
system
man page.
bash
:- Has a
-p
option influencing howeuid
andruid
are treated. - Without
-p
,bash
setseuid
toruid
if they initially differ. - With
-p
, the initialeuid
is preserved. - More details can be found on the
bash
man page.
- Has a
sh
:- Does not possess a mechanism similar to
-p
inbash
. - The behavior concerning user IDs is not explicitly mentioned, except under the
-i
option, emphasizing the preservation ofeuid
andruid
equality. - Additional information is available on the
sh
man page.
- Does not possess a mechanism similar to
These mechanisms, distinct in their operation, offer a versatile range of options for executing and transitioning between programs, with specific nuances in how user IDs are managed and preserved.
Examples taken from https://0xdf.gitlab.io/2022/05/31/setuid-rabbithole.html#testing-on-jail, check it for further information
Objective: Understanding the effect of setuid
in combination with system
and bash
as sh
.
C Code:
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main(void) {
setuid(1000);
system("id");
return 0;
}
Compilation and Permissions:
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
Analysis:
ruid
andeuid
start as 99 (nobody) and 1000 (frank) respectively.setuid
aligns both to 1000.system
executes/bin/bash -c id
due to the symlink from sh to bash.bash
, without-p
, adjustseuid
to matchruid
, resulting in both being 99 (nobody).
C Code:
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main(void) {
setreuid(1000, 1000);
system("id");
return 0;
}
Compilation and Permissions:
oxdf@hacky$ gcc b.c -o /mnt/nfsshare/b; chmod 4755 /mnt/nfsshare/b
Execution and Result:
bash-4.2$ $ ./b
uid=1000(frank) gid=99(nobody) groups=99(nobody) context=system_u:system_r:unconfined_service_t:s0
Analysis:
setreuid
sets both ruid and euid to 1000.system
invokes bash, which maintains the user IDs due to their equality, effectively operating as frank.
Objective: Exploring the interaction between setuid and execve.
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main(void) {
setuid(1000);
execve("/usr/bin/id", NULL, NULL);
return 0;
}
Execution and Result:
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
Analysis:
ruid
remains 99, but euid is set to 1000, in line with setuid's effect.
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;
}
Execution and Result:
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
Analysis:
- Although
euid
is set to 1000 bysetuid
,bash
resets euid toruid
(99) due to the absence of-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;
}
Execution and Result:
bash-4.2$ $ ./e
bash-4.2$ $ id
uid=99(nobody) gid=99(nobody) euid=100
{% 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
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.