Privilege Programs
Set-UID Programs
Attacks on Set UID Programs
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
.
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 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.
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.
Password Dilemma
Permissions of /etc/shadow
File limits access.
Normal users need a way to change their password.
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.
passwd
program is stored at /etc/passwd
.
This program allows users to modify the shadow file.
Normal users cannot directly modify the shadow file.
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.
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.
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
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.
A Set-UID program has a special marking (Set-UID bit).
/bin/id
command is used to print the user IDs of running processes.
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=...
Change the owner of a file to root.
Enable Set-UID bit using chmod 4755 <filename>
.
Shows how a normal program can become privileged with root or other user privileges.
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.
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.
User Inputs
System Inputs
Environment Variables
Non-privileged Process Controlled by User
Explicit Inputs:
Buffer Overflow: Overflowing a buffer to run malicious code.
Format String Vulnerability: Changing program behavior using user inputs as format strings.
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.
Check available shells: cat /etc/shells
.
Check current shell: cat /etc/passwd
.
Change shell: chsh -s <shellname> <username>
.
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.
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.
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.
/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.
Create a directory testCapLeak
.
Create cap_leak.c
with the code in the next slide.
#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;
}
Compile: $ gcc -o cap_leak cap_leak.c
.
Change owner: $ sudo chown root cap_leak
.
Make it Set-UID: $ sudo chmod 4755 cap_leak
.
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
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
).
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)
).
#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;
}
Recompile the program with the fix (closing the file descriptor).
Run the steps to see if the capability leak is happening or not.
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.
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.
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?
#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;
}
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.
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
#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;
}
Attack failed when attempting to inject commands.
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: Don’t mix code and data.
Attacks due to violation of this principle:
system()
code execution.
SQL injection.
Buffer Overflow attacks.
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.
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