Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#ccccff
/* 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 
 */

Supplemental Group Privileges

Any user, including root, may belong to multiple groups; these are handled by supplemental group privileges. The getgroups() function returns an array of group IDs, and the setgroups() function can set the array to an arbitrary array, but usually only if the user has root privileges. While POSIX defines the getgroups() function, it does not define setgroups().

Under normal circumstances setuid() and related calls do not alter the supplemental group privileges. However, a setuid-root program can grant itself supplemental group ids and then relinquish root privileges, in which icase it maintains the supplemental group ids, but lacks the privilege necessary to relinquish them. Consequently, it is recommended that a program relinquish supplemental group privileges immediately before relinquishing root privileges.

POS37-C. Ensure that privilege relinquishment is successful discusses how to drop supplemental group privileges. To ensure that supplemental group privileges are indeed relinquished, you can use the following eql_sups function:

Code Block
bgColor#ccccff

/* Returns nonzero if the two group lists are equivalent (taking into
   account that the lists may differ wrt the egid */
int eql_sups(const int cursups_size, const gid_t* const cursups_list,
	     const int targetsups_size, const gid_t* const targetsups_list) {
  int i;
  int j;
  const int n = targetsups_size;
  const int diff = cursups_size - targetsups_size;
  const gid_t egid = getegid();
  if (diff > 1 || diff < 0 ) {
    return 0;
  }
  for (i=0, j=0; i < n; i++, j++) {
    if (cursups_list[j] != targetsups_list[i]) {
      if (cursups_list[j] == egid) {
	i--; /* skipping j */
      } else {
	return 0;
      }
    }
  }
  /* If reached here, we're sure i==targetsups_size. Now, either
     j==cursups_size (skipped the egid or it wasn't there), or we didn't
     get to the egid yet because it's the last entry in cursups */
  return j == cursups_size ||
    (j+1 == cursups_size && cursups_list[j] == egid);
}

System-Specific Capabilities

Many systems have nonportable privilege capabilities that, if unchecked, can yield privilege escalation vulnerabitilites.

File System Access Privileges (Linux)

Wiki Markup
Processes on Linux have two additional values called {{fsuid}} and {{fsgid}}. These indicate the privileges used when accessing files on the file system. These values normally shadow the effective user ID and effective group ID, but the {{setfsuid()}} and {{setfsgid()}} functions allow them to be changed.  Since changes to the {{euid}} and {{egid}} normally also apply to {{fsuid}} and {{fsgid}}, a program relinquishing root privileges need not be concerned with setting {{fsuid}} or {{fsgid}} to safe values. However, there has been at least one kernel bug that violated this invariant (\[[Chen 02|AA. C References#Chen 02]\] and \[[Tsafrir 08|AA. C References#Tsafrir 08]\]). Consequently, a prudent program will check that {{fsuid}} and {{fsgid}} have harmless values after relinquishing 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.

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[Chen 02|AA. C References#Chen 02]\] "Setuid Demystified"
\[[Dowd 06|AA. C References#Dowd 06]\] Chapter 9, "Unix I: Privileges and Files"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "XYO Privilege Sandbox Issues"
\[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 250|http://cwe.mitre.org/data/definitions/250.html], "Execution with Unnecessary Privileges," [CWE ID 273|http://cwe.mitre.org/data/definitions/273.html], "Failure to Check Whether Privileges Were Dropped Successfully"
\[[Open Group 04|AA. C References#Open Group 04]\] [{{setuid()}}|http://www.opengroup.org/onlinepubs/009695399/functions/setuid.html], [{{getuid()}}|http://www.opengroup.org/onlinepubs/009695399/functions/getuid.html], [{{seteuid()}}|http://www.opengroup.org/onlinepubs/009695399/functions/seteuid.html]
\[[Tsafrir 08|AA. C References#Tsafrir 08]\] "The Murky Issue of Changing Process Identity: Revising 'Setuid Demystified'"
\[[Wheeler 03|AA. C References#Wheeler 03]\] [Section 7.4, "Minimize Privileges"|http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/minimize-privileges.html]

...