Versions Compared

Key

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

...

Code Block
bgColor#ffcccc
/* 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 UIDs over time might be as follows:

...

Description

Code

EUID

RUID

SSUID

program startup

 

0

user

0

temporary drop

seteuid(getuid())

user

user

0

restore

seteuid(0)

user

user

0

permanent drop

setuid(getuid())

user

user

0

restore (attacker)

setuid(0)

0

0

0

...

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

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.

...