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 thePATH
environment variable to locatels
.Attack: Manipulate the
PATH
variable to control how thels
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
programStarts 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 containccccccc
).
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 hereInput 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()
andsetuid()
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