...
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 can regain elevated privileges! */ |
If the program is run as a setuid root program, the state of the UID
s over time might be as follows:
...
Description | Code | EUID | RUID | SSUID |
---|---|---|---|---|
program startup |
| 0 | user | 0 |
temporary drop | | user | user | 0 |
restore | | user | user | 0 |
permanent drop | | user | user | 0 |
restore (attacker) | | 0 | 0 | 0 |
...
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 cannot 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 cannot regain elevated privileges */ |
Supplementary Group IDs
...
Automated Detection
Klocwork Version 8.0.4.16 can detect violations of this rule with the SV.FIU.PERMISSIONS and SV.USAGERULES.PERMISSIONS checkers. See Klocwork Cross Reference
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...