...
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.
...