AB

Set-UID Privileged Programs

Set-UID Privileged Programs

Agenda

  • Privilege Programs

    • Set-UID Programs

    • Attacks on Set UID Programs

Privileged Program

  • A program that is privileged can perform important tasks/jobs which a normal user cannot do.

  • Privileged programs are needed by operating systems.

  • Example: Changing Password in Linux.

  • Users’ password stored in shadow file located at /etc/shadow.

Linux Shadow File

  • The shadow file contains user password information.

  • Only root has write access to shadow file.

  • Sample content:

    root: $6$4GXAA08JSAB7vFKLSCxtVdVMcPav8jZ5u4ZsyG22hy1cqWPdnQgqL84VesJNQYFXSwhfwkhT
    UeHNXYwjjUGe8U/sjITBhq/:16672::::::
    bin:x:14871::::::
    ...
    joe: $6$TA4PslzF$ch961z/ppk1VrmVAqSjSEDF75FIahttselx/bsDdjSXL t8cms IoX9eAKfVm8epuD
    KGVYV1xkohA37ae Evmu8d1:16672:0:99999:7:::
    

Basic File Protection in Linux

  • Basic protection mechanism:

    • Access Control: Each user has different access permissions on a file.

    • User Isolation: Each user is identified by User ID (UID).

    • Root has a UID of 0.

  • When a user accesses a resource/file:

    • Each file has an Access Control List (ACL).

    • ACL describes user permissions: Owner, Group, Other.

  • If a file is created by user2:

    • user2 is the owner with read, write, and execute permissions.

    • The group (e.g., cit_faculty) has read and execute permissions.

    • Others have no permissions.

Shadow File Permission

  • The shadow file is writable only by root.

  • Permissions can be found using ls -l.

  • Normal users can change their password even though they don't have write access to the shadow file.

  • Problem: How would normal users change their password?

  • A normal user is not allowed to access shadow file.

Need for Privileged Programs

  • Password Dilemma

  • Permissions of /etc/shadow File limits access.

  • Normal users need a way to change their password.

Two-Tier Approach

  • Fine-grained access control can overcomplicate OS.

  • OS relies on extensions, i.e., privileged programs, to enforce fine-grained access control.

  • Example: passwd program in Linux to change passwords.

Privileged Programs

  • passwd program is stored at /etc/passwd.

  • This program allows users to modify the shadow file.

  • Normal users cannot directly modify the shadow file.

Types of Privileged Programs

  • Daemons:

    • Background process that runs as root.

    • System can use a root daemon to change the password upon request by a normal user.

  • Set-UID Programs:

    • Marked with a special bit.

    • The OS treats them specially.

Superman Story (Analogy for Set-UID)

  • Power Suit:

    • Directly giving power to superpeople has issues (bad superpeople).

  • Power Suit 2.0 (Computer chip):

    • Specific task with no way to deviate.

  • Set-UID mechanism: A Power Suit mechanism implemented in Linux OS.

Set-UID Concept

  • Allows user to run a program with the program owner’s privilege.

  • Allows users to run programs with temporary elevated privileges.

  • Example: passwd program
    $ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 41284 Sep 12 2012 /usr/bin/passwd

Set-UID Concept

  • Every process has two User IDs:

    • Real UID (RUID): Identifies the real owner of the process.

    • Effective UID (EUID): Identifies the privilege of a process.

    • Access control is based on EUID.

  • Normal program execution:

    • RUID = EUID = User's ID.

  • Set-UID program execution:

    • RUID ≠ EUID: RUID = User's ID, EUID = Program owner's ID.

    • If the program is owned by root, the program runs with root privilege.

How it Works

  • A Set-UID program has a special marking (Set-UID bit).

  • /bin/id command is used to print the user IDs of running processes.

Example

  • Copy /usr/bin/id to ./myid.

  • Change owner to root: sudo chown root myid.

  • Without Set-UID bit enabled, running ./myid shows the user's UID and GID.

  • Enable Set-UID bit: sudo chmod 4755 myid.

  • Running ./myid now shows the user's UID and GID, and effective UID (EUID) as root (0).
    $ cp /usr/bin/id ./myid $ ls myid $ sudo chown root myid $ ./myid uid=1000(cit4520) gid=1000(cit4520) groups=... $ sudo chmod 4755 myid $ ./myid uid=1000(cit4520) gid=1000(cit4520) euid=0(root) groups=...

Turn a Program into Set-UID

  • Change the owner of a file to root.

  • Enable Set-UID bit using chmod 4755 <filename>.

Example of Set UID

  • Shows how a normal program can become privileged with root or other user privileges.

How is Set-UID Secure?

  • Allows normal users to escalate privileges in a restricted way.

  • Restricted behavior:

    • Users can only do what is coded in the Set-UID program.

  • It is unsafe to turn all programs into Set-UID.

  • Examples:

    • /bin/sh: Can execute other programs specified by the user.

    • vi: Text editor that can run user-specified external commands.

Attack on Superman (Analogy for Attacks)

  • Coding flaws can be exploited.

  • Example:

    • Superperson is supposed to fly north then turn left, but can be tricked to fly north and turn west.

Attack Surfaces of Set-UID Programs

  • User Inputs

  • System Inputs

  • Environment Variables

  • Non-privileged Process Controlled by User

Attacks via User Inputs

  • Explicit Inputs:

    • Buffer Overflow: Overflowing a buffer to run malicious code.

    • Format String Vulnerability: Changing program behavior using user inputs as format strings.

Attacks via User Inputs

  • CHSH (Change Shell):

    • Set-UID program to change default shell programs.

    • Shell programs are stored in /etc/passwd.

    • Users specify the name of the shell program (e.g., /bin/bash).

    • Command: cat /etc/shells

  • Issues:

    • Failing to sanitize user inputs.

    • Attackers could create a new root account.

Try this

  • Check available shells: cat /etc/shells.

  • Check current shell: cat /etc/passwd.

  • Change shell: chsh -s <shellname> <username>.

Attacks via Environment Variables

  • Program behavior can be influenced by inputs not visible inside a program.

  • Environment Variables:

    • Set of named-values (e.g., PATH).

    • Can be set by a user before running a program.

Attacks via Environment Variables

  • PATH Environment Variable:

    • Used by shell programs to locate a command if the user does not provide the full path.

    • system(“ls”) calls /bin/sh first.

    • /bin/sh uses the PATH environment variable to locate ls.

    • Attack: Manipulate the PATH variable to control how the ls command is found.

    • Attacker can create their own ls file and modify the $PATH variable.

Capability Leaking

  • Privileged programs downgrade themselves during execution.

  • Example: The su program

    • Starts with EUID as root and RUID as user1.

    • After password verification, both EUID and RUID become user2’s.

  • Programs may not clean up privileged capabilities before downgrading.

Attacks via Capability Leaking: An Example

  • /etc/zzz file is only writable by root.

  • A Set-UID program creates a file descriptor.

  • Privilege is downgraded.

  • Invokes a shell program, lifting behavior restrictions.

Try this Activity

  • Create a directory testCapLeak.

  • Create cap_leak.c with the code in the next slide.

Code for Capability Leaking Example

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    char *v[2];

    fd = open("/etc/zzz", O_RDWR | O_APPEND);
    if (fd == -1) {
        printf("Cannot open /etc/zzz\n");
        exit(0);
    }

    printf("fd is %d\n", fd);
    setuid(getuid());

    v[0] = "/bin/sh";
    v[1] = NULL;
    execve(v[0], v, NULL);

    return 0;
}

Steps to Demonstrate Capability Leak

  • Compile: $ gcc -o cap_leak cap_leak.c.

  • Change owner: $ sudo chown root cap_leak.

  • Make it Set-UID: $ sudo chmod 4755 cap_leak.

Steps to Setup the Vulnerable File

  • Create /etc/zzz: $ sudo gedit /etc/zzz.

  • Add content: bbbbbbbbbbb.

  • Make it root-writable only: $ sudo chown root /etc/zzz && sudo chmod 0644 /etc/zzz

Demonstrate the Capability Leak

  • Try to write to /etc/zzz: $ echo aaaaaaa > /etc/zzz (should fail).

  • Run the Set-UID program: ./cap_leak.

  • In the shell, write to the file descriptor: echo cccccccc >& 3.

  • Check /etc/zzz: $ cat /etc/zzz (it will contain ccccccc).

Attacks via Capability Leaking (Continued)

  • The program forgets to close the file, so the file descriptor is still valid.

  • Fix: Destroy the file descriptor before downgrading the privilege (close(fd)).

Modified Program to Prevent Capability Leak

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    char *v[2];

    fd = open("/etc/zzz", O_RDWR | O_APPEND);
    if (fd == -1) {
        printf("Cannot open /etc/zzz\n");
        exit(0);
    }

    printf("fd is %d\n", fd);
    close(fd);  // Close the file descriptor
    setuid(getuid());

    v[0] = "/bin/sh";
    v[1] = NULL;
    execve(v[0], v, NULL);

    return 0;
}

Follow Earlier Steps

  • Recompile the program with the fix (closing the file descriptor).

  • Run the steps to see if the capability leak is happening or not.

Invoking Programs

  • Invoking external commands are common inside programs.

  • Be careful of external commands in Set-UID programs.

  • Set-UID programs may end up executing unintended programs.

  • External command is chosen by the Set-UID program.

  • Users are not supposed to provide the command.

  • Attack: User input data may be turned into a command name.

Scenario

  • Mallory needs to read all files in a company's Unix system for auditing.

  • She is not allowed to modify any files.

  • Vince (superuser) wrote a Set-UID program that runs /bin/cat to display the contents of a file.

  • Vince is confident that Mallory cannot modify any file.

Invoking Programs: Unsafe Approach

  • The easiest way to invoke an external command is the system() function.

  • The program is supposed to run the /bin/cat program.

  • Question: Can you run other commands with root privilege using this program?

Code for Unsafe Program Invocation

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    char *cat = "/bin/cat";

    if (argc < 2) {
        printf("Please type a file name.\n");
        return 1;
    }

    char *command = malloc(strlen(cat) + strlen(argv[1]) + 2);
    sprintf(command, "%s %s", cat, argv[1]);
    system(command);

    free(command);
    return 0;
}

Steps to Exploit the Unsafe Program

  • Write the program (e.g., catall.c).

  • Compile the program: $ gcc -o catall catall.c.

  • Change the owner to root: $ sudo chown root catall.

  • Change the permission to 4755: $ sudo chmod 4755 catall.

  • Create myfile with content "This is my file".

  • Create rootfile owned by root with permission 644.

  • Run: ./catall "myfile; rm rootfile".

  • Check if rootfile is removed.

Invoking Programs Safely: using execve()

  • execve(v[0], v, 0) command name is provided here

  • Input data are provided here, and can be by user

  • Why is it is safe, Code and data are separated; there is no way for the data to become code

Safe Code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    char *filename = argv[1];
    char * const argv_exec[] = {"/bin/cat", filename, NULL};
    char * const envp[] = {NULL};

    execve(argv_exec[0], argv_exec, envp);
    perror("execve"); // Print error if execve fails
    return 1;
}

Invoking Programs Safely (Continued)

  • Attack failed when attempting to inject commands.

Invoking External Commands in Other Languages

  • Risk of invoking external commands is not limited to C programs.

  • Avoid problems similar to those caused by the system() functions.

  • Examples:

    • Perl: open() function can run commands.

    • PHP: system() function.

  • Attack: http://localhost/list.php?dir=.;date -> Command executed on server : /bin/ls .;date

Principle of Isolation

  • Principle: Don’t mix code and data.

  • Attacks due to violation of this principle:

    • system() code execution.

    • SQL injection.

    • Buffer Overflow attacks.

Principle of Least Privilege

  • A privileged program should only be given the power required to perform its tasks.

  • Disable privileges when not needed.

  • In Linux, seteuid() and setuid() can be used to disable/discard privileges.

Summary

  • The need for privileged programs

  • How the Set-UID mechanism works

  • Security flaws in privileged Set-UID programs

  • Attack surface

  • How to improve the security of privileged programs