...
| Code Block | ||
|---|---|---|
| ||
/* Code intended to run with elevated privileges */
/* Temporarily drop privileges */
if (seteuid(getuid()) != 0) {
/* Handle error */
}
/* Code intended to run with lower privileges */
if (need_more_privileges) {
/* Restore privileges */
if (seteuid(0) != 0) {
/* Handle Error */
}
/* Code intended to run with elevated privileges */
}
/* ... */
/* Permanently drop privileges */
if (setuid(getuid()) != 0) {
/* Handle Error */
}
/* Code intended to run with lower privileges,
but if privilege relinquishment failed,
attacker could regain elevated priveleges! */
|
If the program is run with as a setuid root program, the state of the UID's over time might be:
...
| Code Block | ||
|---|---|---|
| ||
/* Code intended to run with elevated privileges */
/* Temporarily drop privileges */
if (seteuid(getuid()) != 0) {
/* Handle error */
}
/* Code intended to run with lower privileges */
if (need_more_privileges) {
/* Restore Privileges */
if (seteuid(0) != 0) {
/* Handle error */
}
/* Code intended to run with elevated privileges */
}
/* ... */
/* Permanently drop privileges */
if (setuid(getuid()) != 0) {
/* Handle error */
}
if (setuid(0) != -1) {
/* Privileges can be restored, handle error */
}
/* Code intended to run with lower privileges;
attacker can not regain elevated privileges */
|
Compliant Solution
A better solution is to ensure that proper privileges exist before attempting to carry out a permanent drop.
| Code Block | ||
|---|---|---|
| ||
/* Store the privileged ID for later verification */
uid_t privid = geteuid();
/* Code intended to run with elevated privileges */
/* Temporarily drop privileges */
if (seteuid(getuid()) != 0) {
/* Handle error */
}
/* Code intended to run with lower privileges */
if (need_more_privileges) {
/* Restore Privileges */
if (seteuid(privid) != 0) {
/* Handle error */
}
/* Code intended to run with elevated privileges */
}
/* ... */
/* Restore privileges if needed */
if (geteuid() != privid) {
if (seteuid(privid) != 0) {
/* Handle error */
}
}
/* Permanently drop privileges */
if (setuid(getuid()) != 0) {
/* Handle error */
}
if (setuid(0) != -1) {
/* Privileges can be restored, handle error */
}
/* Code intended to run with lower privileges;
attacker can not regain elevated privileges */
|
Risk Assessment
If privilege relinquishment conditions are left unchecked, any flaw in the program may lead to unintended system compromise corresponding to the more privileged user or group account.
...