Reference no: EM133063915 
                                                                               
                                       
Environment Variable and SET-UID Lab
Aims and Objectives
The  learning objective of this lab is for students to understand how  environment variables affect program and system behaviours. 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 behaviours, 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 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 behaviours. We are particularly interested in how  environment variables affect the behaviour 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
Task 1: Understanding login shells
In this task, we study the commands that can be used to set and unset environment variables. We
are using the Bash shell in the ‘uwe' user 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  using the command chsh (please do not do it for this lab).
Here is the output from the tail of the default UWECyber VM /etc/passwd file:
$  tail /etc/passwd geoclue:x:122:127::/var/lib/geoclue:/usr/sbin/nologin  pulse:x:123:128:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:124:65534::/run/gnome-initial- setup/:/bin/false
gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false ubuntu:x:1000:1000:Ubuntu,,,:/home/ubuntu:/bin/bash
systemd-coredump:x:999:999:systemd  Core Dumper:/:/usr/sbin/nologin  sshd:x:126:65534::/run/sshd:/usr/sbin/nologin  vboxadd:x:998:1::/var/run/vboxadd:/bin/false  uwe:x:1001:1001::/home/uwe:/bin/bash  telnetd:x:127:133::/nonexistent:/usr/sbin/nologin
Question: What is the difference between a user shell of /usr/sbin/nologin and /bin/false? Explain the difference.
Task 2: Manipulating Environment Variables
Please execute the following tasks:
• Use the 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 the Bash's internal commands (you will not be able to find them  outside of Bash).
Proof: Demonstrate proof of executing the above commands.
Task 3: 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 (please see the  manual of fork() by typing the following command: man fork). In this  task, we would like to know whether the parent's environment variables  are inherited by the child process or not.
Step 1. Please compile and  run the program in Code Listing 1, and describe your observation.  Because the output contains many lines, you should save the output into a  file, such as using a.out
> child (assuming that a.out is your executable file name and you are testing the child process functionality).
Step 2.  Now comment out the printenv() statement in the child process case  (Line ?), and uncomment the printenv() statement in the parent process  case (Line).
Compile and run the code again, saving the output in another file.
Question: Describe your observations between the two programs and suggest why this may be.
Task 4: 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; execve() does not return on  success, and the text, initialized data, uninitialized data (bss), and  stack of the calling process are overwritten according to the contents  of the newly loaded program.
Essentially, execve() runs the new program inside the calling process.
If  the set-user-ID bit is set on the program file referred to by execve(),  then the effective user ID of the calling process is changed to that of  the owner of the program file.
You should refer to the manual page  for execve() for more details about the parameters that are passed to  it. Execute the command man execve on the command line to see the manual  page for this program.
We are interested in what happens to the environment variables; are they automatically inherited by the new program?
Step  1. Please compile and run the program in Code Listing 2 and describe  your observation. This program simply executes a program called  /usr/bin/env, which prints out the environment variables of the current  process.
Question: Describe your observations of the program and explain what you think is happening.
Step 2. Change the invocation of execve() in Line ? to the following;
execve("/usr/bin/env", argv, environ);
Question: Describe your observations of the changed program.
Step 3.
Question: Please draw your conclusion regarding how the new program gets its environment variables.
Task 5: 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 it uses the function
execl() to execute /bin/sh
execl()  subsequently calls execve(), passing to it the environment variables  array. Therefore, as we saw in the previous task using system(), the  environment variables of the calling process is passed to the new  program /bin/sh.
Task 6: Environment Variable and Set-UID Programs
Set-UID is an important security mechanism in Unix operating systems. When a Set-UID
program  runs, it assumes the owner's privileges. For example, if the program's  owner is root, then when anyone runs this program, the program gains the  root's privileges during its execution.
Set-UID allows us to do many  interesting things, but it escalates the user's privilege when  executed, making it quite risky. Although the behaviours of Set-UID  programs are decided by their program logic, not by users, users can  indeed affect the behaviours 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 program's process  from the user's process.
Step 1. Write the following program that can print out all the environment variables in the current process.
Step 2. Compile the above program, change its ownership to root, and ma
ke it a Set-UID program.
Step 3.  In your shell (you need to be in a normal user account such as uwe, not  the root account), use the echo and export commands to check the  following environment variables:
Ensure  that you change the <YOUR_SURNAME> to be your surname These  environment variables are now set in the user's shell process.
Now,  run the Set-UID program from Step 2 in your shell. After you type the  name of the program in your shell, the shell forks a child process, and  uses the child process to run the program.
Please check whether all  three environment variables you set in the shell process (parent) are  visible in the Set-UID child process.
Question: Describe your observation. If there are differences, describe them and why you think this may be happening.
Task 7: The PATH Environment Variable and Set-UID Programs
Because  the /bin/sh program is invoked, calling system() within a Set-UID  program is quite dangerous. This is because the actual behaviour of the  shell program can be affected by environment variables, such as PATH.
An  environment variable such as $PATH is provided by the user, who may be  malicious. By changing these variables, malicious users can control the  behaviour of the Set-UID program.
In Bash, you can change an  environment variable such as the PATH variable in the following way  (this example adds the directory /home/uwe to the beginning of the PATH  environment variable):
$ export PATH=/home/uwe:$PATH
The Set-UID  program in Code Listing 5 is supposed to execute the /bin/ls command;  however, it has a security flaw as the programmer only uses the relative  path for the ls command, rather than the absolute path:
Please:
• Compile the program in Code Listing 5
• Change its owner to root
• Make it a Set-UID program.
Without  modifying the code in Code Listing 5, use this Set-UID program to give  you a root shell prompt instead of running ls. Prove that you have  gained a root shell by issuing the whoami command in the new shell  prompt.
Question: Describe and demonstrate how you gained a root  shell by exploiting the security flaw in the program from Code Listing 5
Suggest how the programmer could have avoided the security flaw in the program.
Task 8: 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_LIBRARY_PATH, and other  LD * influence the behaviour of dynamic loader/linker. A dynamic  loader/linker is the part of an operating system (OS) that loads (from  persistent storage to RAM) 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 binary). Among the  environment variables that affect their behaviours, 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 study LD_PRELOAD.
Step 1. First, we will see how these  environment variables influence the behaviour of dynamic loader/linker  when running a normal program. Please follow these steps:
1. We will now build a dynamic link library. Create the program as shown in Code Listing 6, and name it mylib.c.
If we  run a program that uses our dynamically linked library it will override  the default sleep() function in libc and print our text out instead:
2. We  can compile the above program using the following commands (in the -lc  argument, the second character is a lower case ‘L' not a ‘1'/'one'):
3. Now, set the LD PRELOAD environment variable so that the system knows about out dynamic link library:
4.  Finally, compile the program in Code Listing 7 and call it task8.c.  Ensure that it is in the same directory as the above dynamic link  library libmylib.so.1.0.1:
5. Make four copies of the executable. Call them task8-a, task8-b, task8-c, and task8-d
Step 2.  After you have done the above, please run the task8 executables under  the following conditions, and observe what happens. (NOTE: pay close  attention to the instructions!). If the program picks up our dynamic  library, it should print our text. If it uses the default system sleep()  library, then it will sleep for 1 second and return the CLI prompt  without printing anything.
1. Leave task8-a as normal program and run it as the normal uwe user.
2. Change task8-b so that it is a root owned, Set-UID program (Use chown and chmod), and run it as the uwe user.
3.  Change task8-c so that it is a ubuntu owned, Set-UID program. (ubuntu is  another user that is already present in this VM). Run this program as  the uwe user.
4.  Change task8-d so that it is a root owned, Set-UID program. Change the  shell to the root account using the command "sudo su". We are now  running this program as the root user in the root account.
Export the LD_PRELOAD environment variable again in the root account and run the
task8-d program.
Question:  You should be able to observe two different behaviours in the scenarios  described above, even though you are running the same program. Note the  different behaviours of the 4 programs here.
Step 3. Explain why the behaviours in the four different programs in Step 2 are different.
Task 9: Invoking External Programs Using system() versus 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 affect the behaviour of  system(), because the variable affects how the shell works. execve()  does not have the problem, because it does not invoke a shell. Invoking a  shell has another dangerous security consequence, and this time, it has  nothing to do with environment variables. Let us look at the following  scenario.
Bob works for an auditing agency, and he needs to  investigate a company for a suspected fraud. For the investigation  purpose, Bob needs to be able to read all the files in the company's  Unix system; on the other hand, to protect the integrity of the system,  Bob should not be able to modify any file.
To achieve this goal,  Vince, the superuser of the system, wrote a special set-root-uid program  (see Code Listing 8), and then gave the executable permission to Bob.  This program requires Bob to type a file name at the command line, and  then it will run /bin/cat to display the specified file. Since the  program is running as a root, it can display any file Bob specifies.  However, since the program has no write operations, Vince is very sure  that Bob cannot use this special program to modify any file.
Step 1: Compile  the program in Code Listing 8, make it a root-owned Set-UID program.  Initially, the program will use the system()command to invoke the  ‘/bin/cat' command.
Without modifying the code exploit the security flaw in the program and gain a root shell prompt.
Demonstrate your attack and describe how it works.
Step 2:  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 again. Does your  attack from Step 1 still work?
Question: Please describe and explain the behaviour change.
Task 10: 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  to 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 privileged capabilities when  it was still privileged; when the privilege is downgraded, if the  program does not clean up those capabilities, they may still be  accessible by the non-privileged process. In other words, although the  effective user ID of the process becomes non- privileged, the process is  still privileged because it possesses privileged capabilities.
Compile  the program in Code Listing 9, change its owner to root, and make it a  Set-UID program. Run the program as the uwe user and describe what you  have observed. Before running this program, you should create the file  /etc/uwe file first.
Question:  Will the file /etc/uwe be modified? Please explain your observation as  to why or why not the file is able to be modified.
Lab Clean-up
Restore  the symlink for /bin/sh to point to /bin/dash which we modified in  section 2.7 - Task 7: The PATH Environment Variable and Set-UID Programs
Further research and a real-world case study
Produce a 500 to 800-word report detailing the following:
1.  Investigate and explain how the dash shell countermeasures work with  regard to dash preventing itself from being executed in a Set-UID  process. (Guidance - 200 words)
2. A  real-world case study involving security issues with privileged SetUID  binaries. For example, CVE-2021-41387 was published on 17th September  2021, which demonstrates that these basic issues security principles can  still be lacking today.
Find  and research a real-world case study involving SET-UID programs. Explain  in your own words what the security incident was, how the incident  arose, and any potential mitigations that could have been taken to avoid  the issue. (Guidance - 500 words)
You are expected develop your  academic writing and to be succinct yet clear in your answer to address  the required word count. Your report should include relevant references  from the literature, referenced and cited correctly using UWE Harvard  style.
Attachment:- Environment Variable and SET-UID Lab.rar