SetUID: Live Demo

Real and Effective User ID

  • Across setuid() (either via system call or the setuid bit), the original user ID (where we came from) is remembered ⟶ effective user ID

  • The user ID that was changed to is the real user ID. It is this user ID that defines the process’s permissions!

#include <unistd.h>
#include <sys/types.h>

uid_t getuid(void);
uid_t geteuid(void);

man getuid

Sample Program

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>


int main(void)
{ 
    printf("%d\n", getuid());
    printf("%d\n", geteuid());
    return 0;
}
  • Build

    $ gcc -o uid uid.c
    
  • Look

    $ ls -l uid
    -rwxrwxr-x. 1 jfasch jfasch 24456 Mar  3 14:34 uid
    $ id -u jfasch
    1000
    
  • Run

    $ ./uid
    1000
    1000
    

Set-UID jfasch?

  • Set the Set-UID bit

    $ chmod 4755 uid
    

    … or …

    $ chmod u+s uid
    
  • Look

    $ ls -l uid
    -rwsr-xr-x. 1 jfasch jfasch 24456 Mar  3 14:34 uid
    
  • Run as user jfasch ⟶ no difference (obviously)

    $ ./uid 1000 1000

  • Run as user someone-else (using sudo 🤔)

    $ id -u someone-else
    1001
    $ sudo -u someone-else ./uid
    [sudo] password for jfasch:
    1001
    1000
    

    Caution

    A program that is Set-UID myself could for example, if it wanted, remove my home directory!

  • Run as root

    $ sudo ./uid
    0
    1000
    

Set-UID root? Danger!

  • Let root own program, and run (⟶ still runs as jfasch)

    $ sudo chown root uid
    $ ls -l uid
    -rwxr-xr-x. 1 root jfasch 24456 Mar  3 14:34 uid
    $ ./uid
    1000
    1000
    
  • Set-UID root

    $ sudo chmod u+s uid
    $ ls -l uid
    -rwsr-xr-x. 1 root jfasch 24456 Mar  3 14:34 uid
    
  • Run

    $ ./uid
    1000
    0
    

Caution

A program that is Set-UID root could for example, if it wanted, erase the entire disk!