Get a Pentest and security assessment of your IT network.

Cyber Security

Bash: SUID Child Process UID Issue

TL;DR

A child process spawned by a SUID program may not inherit the parent’s effective user ID (EUID) if certain conditions are met, particularly when using exec family functions. This guide explains why and how to fix it.

Understanding the Problem

When a program is set with the SUID bit, it runs with the permissions of the file owner (typically root). Normally, any child processes created by this program should also run with those elevated privileges. However, there are scenarios where this doesn’t happen.

Why Child Processes Might Not Inherit UID

  1. exec Family Functions: Using functions like execve, execl, or execvp can cause the child process to lose the elevated privileges if not handled correctly.
  2. Setuid/Setgid Issues: Incorrectly setting up setuid and setgid bits in the program’s environment can lead to privilege dropping.
  3. Shell Scripting: Shell scripts are interpreted, not directly executed, which affects how SUID works. Direct execution of binaries is preferred for SUID programs.

Solution Guide

  1. Use Direct Binary Execution (Preferred): Avoid using shell scripts as SUID programs whenever possible. Compile your program directly into an executable binary.
    • Shells often reset the effective UID/GID of child processes, negating the SUID effect.
  2. Ensure Proper exec Usage: If you must use exec functions, make sure they are called correctly within your C code.
    #include <unistd.h>
    int main() {
      uid_t uid = geteuid();
      if (uid != 0) {
        // Program is not running as root, handle error or exit
        return 1;
      }
      execl("/bin/bash", "bash", "-c", "whoami", NULL);
      perror("exec failed"); // Check for errors after exec
      return 1;
    }
  3. Verify Effective UID After Fork: Immediately after a fork() call, check the effective user ID of the child process.
    #include <unistd.h>
    #include <stdio.h>
    int main() {
      pid_t pid = fork();
      if (pid == 0) { // Child Process
        uid_t uid = geteuid();
        printf("Child process UID: %dn", uid);
        // Continue with your program logic
      } else if (pid > 0) { // Parent Process
        // ...
      }
      return 0;
    }
  4. Avoid Unnecessary Privilege Dropping: Don’t explicitly call functions like setuid() or setgid() unless absolutely necessary. These can unintentionally lower the privileges.
  5. Check Environment Variables: Ensure that environment variables aren’t interfering with the SUID behavior. Some variables might reset UID/GID.
    • Use getenv("HOME") to check if the HOME variable is set, as it can sometimes cause issues.
  6. Setuid Bit Verification: Confirm that the SUID bit is actually set on the executable file using ls -l.
    ls -l /path/to/your/executable

    The output should show an ‘s’ in the permissions field (e.g., -rwsr-xr-x). If it shows an ‘S’, the SUID bit is set but the program isn’t running as root.

Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation