Question
The learning objective of this lab is for students to understand how environment variables affect program and system behaviors. Environment variables are a set of
The learning objective of this lab is for students to understand how environment variables affect program and system behaviors. Environment variables are a set of dynamic named values that can affect the way running processes will behave on a computer. They are used by most operating systems, since they were introduced to Unix in 1979. Although environment variables affect program behaviors, how they achieve that is not well understood by many programmers. As a result, if a program uses environment variables, but the programmer does not know that that they are used, the program may have vulnerabilities.
In this lab, students will understand how environment variables work, how they are propagated from parent process to child, and how they affect system/program behaviors. We are particularly interested in how environment variables affect the behavior of Set-UID programs, which are usually privileged programs. This lab covers the following topics:
-
Environment variables
-
Set-UID programs
-
Securely invoke external programs
-
Capability leaking
-
Dynamic loader/linker
Lab environment: SEED Ubuntu 16.04 VM, see separate code document and zip of code files
Submission
Submit a detailed lab report, with screenshots, to describe what you have done and what you have observed. Provide explanation to any observations that are interesting or surprising. Provide explanations for all screenshots included.
Lab Tasks
-
Manipulating Environment Variables
-
Passing Environment Variables from Parent Process to Child Process
-
Environment Variables and execve()
-
Environment Variables and system()
-
Environment Variables and Set-UID Programs
-
The PATH Environment Variable and Set-UID Programs
-
The LD_PRELOAD Environment Variable and Set-UID Programs
-
Invoking External Programs Using system() versus execve()
-
Capability Leaking
Task 1 Manipulating Environment Variables
In this task, we study the commands that can be used to set and unset environment variables. We are using Bash in the seed account. The default shell that a user uses is set in the /etc/passwd file (the last field of each entry). You can change this to another shell program but we will not do that for this lab.
-
Use printenv or env command to print out the environment variables. If you are interested in some particular environment variables, such as PWD, you can use printenv PWD or env | grep PWD.
-
Use export and unset to set or unset environment variables. It should be noted that these two commands are not separate programs; they are two of Bashs internal commands (you will not be able to find them outside of Bash).
Task 2 Passing Environment Variables from Parent Process to Child Process
In this task, we study how a child process gets its environment variables from its parent. In Unix, fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent; however, several things are not inherited by the child. In this task we would like to know whether the parents environment variables are inherited by the child process or not.
-
Compile and run the task2.c program and report what you see. Because the output contains many strings, you should save the output into a file, such as using a.out > child (assuming that a.out is the executable file name).
-
Comment out that printenv() statement in the child process case (Line marked (1)), and uncomment the printenv() statement in the parent process case (Line marked (2)).
-
Compile and run the code again, and report what you see. Save the output in another file.
-
Compare the difference of these two output files using the diff command. What can you conclude?
Task 3 Environment Variables and execve()
In this task, we study how environment variables are affected when a new program is executed via execve(). The function execve() calls a system call to load a new command and execute it; this function never returns. No new process is created; instead, the calling process text, data, bss, and stack are overwritten by that of the program loaded. Essentially, execve() runs the new program inside the calling process. We are interested in what happens to the environment variables; are they automatically inherited by the new program?
-
Compile and run the task3.c program, and report what you see. This program simply executes a program called /usr/bin/env, which prints out the environment variables of the current process.
-
Change the call of execve() in Line marked (1) to the following; report what you see.
execve("/usr/bin/env", argv, environ);
-
What can you conclude about how the new program gets its environment variables?
Task 4 Environment Variables and system()
In this task, we study how environment variables are affected when a new program is executed via the system() function. This function is used to execute a command, but unlike execve(), which directly executes a command, system() actually executes /bin/sh -c command, i.e., it executes /bin/sh, and asks the shell to execute the command.
If you look at the implementation of the system() function, you will see that is uses execl() to execute /bin/sh; execl() calls execve(), passing to it the environment variables array. Therefore, using system(), the environment variables of the calling process are passed to the new program /bin/sh.
1. Compile and run the task4.c program to verify the above.
Task 5 Environment Variables and Set-UID Programs
Set-UID is an important security mechanism in Unix operating systems. When a Set-UID program runs, it assumes the owners privileges. For example, if the programs owner is root, then when anyone runs this program, the program gains the roots privileges during its execution.
Set-UID allows us to do many interesting things, but it escalates the users privilege when executed, making it quite risky. Although the behaviors of Set-UID programs are decided by their program logic, not by users, users can indeed affect the behaviors via environment variables.
To understand how Set-UID programs are affected, let us first figure out whether environment variables are inherited by the Set-UID programs process from the users process.
-
Compile the task5.c program that can print out all the environment variables in the current process.
-
Change its ownership to root, and make it a Set-UID program.
-
In your shell (using the normal seed user account, not the root account), use the export
command to set the following environment variables (they may already exist): a. PATH
b. LD_LIBRARY_PATH
c. Another environmental variable of your choice
-
Run the Set-UID program from step 2. After you type in the name of the program in your
shell, the shell forks a child process, and uses the child process to run the program.
-
Check whether all the environment variables you set in the shell process (parent) get
into the Set-UID child process. Report what you see. Is there anything surprising?
Task 6 The PATH Environment Variable and Set-UID Programs
Because of the shell program invoked, calling system() within a Set-UID program is quite dangerous. That is because the actual behavior of the shell program can be affected by environment variables, such as PATH; these environment variables are provided by the user who may be malicious.
By changing these variables, malicious users can control the behavior of the Set-UID program. In Bash, you can change the PATH environment variable in the following way (this example adds the directory /home/seed to the beginning of the PATH environment variable):
export PATH=/home/seed:$PATH
The Set-UID program below is supposed to execute the /bin/ls command; however, the programmer only uses the relative path for the ls command, rather than the absolute path:
-
Compile the task6.c program.
-
Change its owner to root and make it a Set-UID program.
-
Can you let this Set-UID program run your code instead of /bin/ls? If you can, is your
code running with the root privilege? Report and explain what you see.
Note for Ubuntu 16.04 VM
The system(cmd) function executes the /bin/sh program first, and then asks this shell program to run the cmd command. In the Ubuntu 16.04 VM, /bin/sh is actually a symbolic link pointing to the /bin/dash shell. However, the dash program has a countermeasure that prevents itself from being executed in a Set-UID process. Basically, if dash detects that it is executed in a Set- UID process, it immediately changes the effective user ID to the process real user ID, essentially dropping the privilege.
Since our victim program is a Set-UID program, the countermeasure in /bin/dash can prevent our attack. To see how our attack works without such a countermeasure, we will ink /bin/sh to another shell that does not have such a countermeasure. A shell program called zsh is installed in the Ubuntu 16.04 VM. Use the following commands to link /bin/sh to zsh.
sudo rm /bin/sh sudo ln -s /bin/zsh /bin/sh
Task 7 The LD_PRELOAD Environment Variable and Set-UID Programs
In this task, we study how Set-UID programs deal with some of the environment variables. Several environment variables, including LD_PRELOAD, LD_LIBRART_PATH, and other LD_* influence the behavior of dynamic loader/linker. A dynamic loader/linker is the part of an operating system that loads and links the shared libraries needed by an executable at run time.
In Linux, ld.so or ld-linux.so, are the dynamic loader/linker (each for different types of binaries). Among the environment variables that affect their behaviors, LD_LIBRARY_PATH and LD_PRELOAD are the two that we are concerned with in this lab.
In Linux, LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories. LD_PRELOAD specifies a list of additional, user-specified, shared libraries to be loaded before all others. In this task, we will only look at LD_PRELOAD.
First, we will see how these environment variables influence the behavior of dynamic loader/linker when running a normal program.
-
Use the dynamic link library program mylib.c. It overrides the sleep() function in libc.
-
Compile the mylib.c program using the following commands.
gcc -fPIC -g -c mylib.c gcc -shared -o libmylib.so.1.0.1 mylib.o -lc
-
Set the LD_PRELOAD environment variable.
export LD_PRELOAD=./libmylib.so.1.0.1
-
Compile the myprog.c program in the same directory as the first program.
-
Run myprog under the following conditions:
a. Make myprog a regular program and run it as a normal user b. Make myprog a Set-UID root program and run it as a normal user c. Make myprog a Set-UID root program, export the LD_PRELOAD environment
variable again in the root account and run it
-
Observe the different behaviors of the same program run under the different conditions
above. What do you think causes the difference? Environment variables play a role.
Task 8 Invoking External Programs Using system() vs. execve()
Although system() and execve() can both be used to run new programs, system() is quite dangerous if used in a privileged program, such as Set-UID programs. We have seen how the PATH environment variable affects the behavior of system(), because the variable affects how the shell works. execve() does not have this problem, because it does not invoke shell. Invoking
shell has another dangerous consequence, and this time, it has nothing to do with environment variables. Lets look at a scenario:
Joe works for an auditing agency, and he needs to investigate a company for a suspected fraud. For the investigations purposes, Joe needs to be able to read all the files in the companys Unix system. On the other hand, to protect the integrity of the system, Joe should not be able to modify any file.
To achieve this goal, Annie, the superuser of the system, wrote a special set-root-uid program, and gave executable permission to Joe. This program requires Joe to type a file name at the command line, and the then it will run /bin/cat to display the specified file. Since the program is running as root, it can display any file Joe specifies. However, since the program has no write operations, Annie is confident that Joe cannot use this special program to modify any file.
-
Compile the above program and make it a root-owned Set-UID program.
-
The program uses system() to invoke the command. If you were Joe, could you
compromise the integrity of the system? For example, could you remove a file that is
not writable to you?
-
Comment out the system(command) statement and uncomment the execve()
statement; the program will use execve() to invoke the command.
-
Recompile the program.
-
Make it a root-owned Set-UID program.
-
Do the attacks done in step 3 still work? Report and explain what you see.
Task 9 Capability Leaking
To follow the Principle of Least Privilege, Set-UID programs often permanently relinquish their root privileges if such privileges are not needed anymore. Moreover, sometimes, the program needs to hand over its control to the user; in this case, root privileges must be revoked. The setuid() system call can be used to revoke the privileges. According the manual, setuid() sets the effective user ID of the calling process. If the effective UID of the caller is root, the real UID and saved set-user-ID are also set. Therefore, if a Set-UID program with effective UID 0 calls setuid(n), the process will become a normal process, with all its UIDs being set to n.
When revoking the privilege, one of the common mistakes is capability leaking. The process may have gained some privileges capabilities when it was still privileged; when the privilege was downgraded, if the program does not clean up those capabilities, they may still be accessible by the non-privileged process. Although the effective user ID of the process becomes non-privileged, the process is still privileged because it possesses privileged capabilities.
-
Compile the task9.c program.
-
Change the owner to root and make it a Set-UID program.
-
Run the program as a normal user, report and explain what you see. Will the file /etc/zzz
be modified?
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started