Submit TWO files to Brightspace:
code_package[.tar.gz/.tar.xz/.zip], containing any requested code or script files. The names for these files will be specified in the relevant question.report.pdf, with your answers to assignment questions. At the top of the first page, include all of the following: your full name, your student number and email address, the course number, the assignment number, and the date.Note: Instructions are current as of Sept 2025.
This section explains the setup steps for this assignment (and future ones). You do not have to submit anything for this section.
You will first need to create a Linux virtual machine (VM), to ensure a work environment consistent with your peers. Assignments will refer to sample files included with your VM image, and may rely on specific configurations applied to your VM's OS beforehand.
You will create this VM on the SCS OpenStack platform. This service is only accessible through the campus network or the Carleton VPN. You must also have an active SCS account to log in, and you may need to use the SCS Online Account Management tool if you have not yet done so this term.
After logging in, you will land on the Overview page. To select our course project, COMP4108B-W26, use the drop-down menu at the top-left of the page, to the right of the OpenStack logo. If you are unable to see our project as an option in your drop-down, use the SCS Online Account Management tool to update your account.
comp4108-w26-assignment-01.comp4108b-w26.2Gram.21Gdisk.2cpu.ping-ssh-egress.ext-net-128. Then, click the Allocate IP button. You should now have an available option.By following the previous instructions, you will have an active VM instance running the snapshot image for Assignment 1. This instance will also have an external IP address, and will be allowed to accept connection requests over the SSH protocol. (We will learn more about this protocol in Chapter 10 of the course textbook.) This section describes how to connect to your instance.
Note that you only need to be on the campus network to access the OpenStack UI—your VM will remain reachable via SSH even when off-campus.
Your VM has both an internal and external IP address associated with it. The internal IP address locates your VM from within the OpenStack network – the external IP address locates your VM from outside of it. When configuring remote access, you will need the external one.
192.168.—the other one is your external IP address.If you have never used SSH on the computer you are using to access the VM, you may need to install an SSH client. On MacOS and Linux machines, the OS comes with the ssh command pre-installed. Windows machines might have an OpenSSH client built-in, but for now, we recommend that you still use a mature external client, like MobaXterm or PuTTY.
Since the SCS network is behind a firewall that restricts access, you will need to proxy ("jump") your SSH connection through the SCS external access host (access.scs.carleton.ca) to reach your VM. Do this in one of two ways:
Using the SCS external access host as a proxy (preferred):
MacOS / Linux – Open ~/.ssh/config with your preferred text editor. Create a new entry in this file that looks like the following, substituting any bracketed placeholder values for your own:
Host comp4108
Hostname [your-VM-external-IP-address]
User student
ProxyJump [your-MC1-username]@access.scs.carleton.ca
ExitOnForwardFailure yes
You can now connect to your VM by executing the following command in a terminal: ssh comp4108 .
If you are unable to use the config file, you can apply all of these configuration options at the command line:
ssh -J [your-MC1-username]@access.scs.carleton.ca -o "ExitOnForwardFailure yes" student@[your-VM-external-IP-address]
Windows – This depends on your chosen client. Fill in the host and user information as per above. Look for proxy settings, and use [your-MC1-username]@access.scs.carleton.ca as the proxy host.
SSH from the SCS external access host:
MacOS / Linux / Windows – If you've previously configured your machine to access access.scs.carleton.ca in some other way, you can establish your connection as usual. Then, you can SSH to your VM:
ssh student@[your-VM-external-IP-address]
You can also set up a config at ~/.ssh/config by following the MacOS / Linux steps in the previous option—just omit the ProxyJump and ExitOnForwardFailure directives.
studentYour credentials for logging into your new VM instance are:
studenttneduts!student password on first login. Even if it does not, we highly recommend you change the default password by running the passwd command in your terminal. MacOS / Linux – If you are using the ProxyJump directive, you can log in more securely and efficiently by executing the ssh-copy-id comp4108 command from your personal machine. This will send your SSH client's default public key to your VM for use in subsequent authentications, instead of a password. If you get a No identities found error, run ssh-keygen -t ed25519 to generate your default key pair, then try again.
For most assignments, you will likely be writing scripts on the VM itself. You can send and retrieve files from your VM over the SSH protocol using rsync or scp on MacOS / Linux, or installing an SCP client such as WinSCP on Windows. (Note that MobaXterm already has a client built into it.)
If you use Microsoft's Visual Studio Code, you might be able to connect to your VM using the Remote - SSH extension. Microsoft maintains an extensive guide on this topic, and the SCS also has a relevant article from 2024. Note, however, that these steps will need to be repeated when rebuilding your VM for future assignments.
Relevant textbook sections: 5.3, 5.4, 5.5
This part involves Unix file-based access control mechanisms, as implemented in the Ubuntu OS. All questions should be answered using the student user on your VM—if you do not see student@COMP4108 when writing in your terminal, make sure you reconnect to your VM before continuing.
10 Marks Complete the Bash command-line script provided below, such that it returns, for a specified UID, that user's profile information. There are 5 Bash function stubs for you to fill in, each with a description of what it needs to return:
#!/bin/bash
function get_full_name_for_uid() {
### This function returns the full name (found within the GECOS field) of the associated UID.
### Example: Bruce Wayne
local USER_ID=${1}
echo Placeholder
return 0
}
function get_user_name_for_uid() {
### This function returns the user name of the associated UID.
### Example: bwayne
local USER_ID=${1}
echo Placeholder
return 0
}
function get_primary_gid_for_uid() {
### This function returns the GID of the primary group for the associated UID.
### Example: 1000
local USER_ID=${1}
echo Placeholder
return 0
}
function get_group_name_for_gid() {
### This function returns the name of the primary group for the associated GID.
### Example: bwayne
local GROUP_ID=${1}
echo Placeholder
return 0
}
function get_all_group_names_for_uid() {
### This function returns all group names that the associated UID is a member of, space-separated.
### Example: bwayne batteam
### Hint: If you invoke a function using $() notation, newlines will turn into spaces automatically.
local USER_ID=${1}
echo Placeholder1 Placeholder2
return 0
}
# -------------------------------------------------
# DO NOT EDIT BELOW!
# -------------------------------------------------
function print_profile_for_uid() {
local USER_ID=${1}
local FULL_NAME=$(get_full_name_for_uid ${USER_ID})
local USER_NAME=$(get_user_name_for_uid ${USER_ID})
local PRIMARY_GID=$(get_primary_gid_for_uid ${USER_ID})
local PRIMARY_GROUP_NAME=$(get_group_name_for_gid ${PRIMARY_GID})
local ALL_GROUP_NAMES=$(get_all_group_names_for_uid ${USER_ID})
local OTHER_GROUP_NAMES=""
for GROUP_NAME in ${ALL_GROUP_NAMES}; do
if [ "${GROUP_NAME}" != "${PRIMARY_GROUP_NAME}" ]; then
OTHER_GROUP_NAMES+="${GROUP_NAME}, "
fi
done
if [ ${#OTHER_GROUP_NAMES} -ge 2 ]; then
OTHER_GROUP_NAMES=${OTHER_GROUP_NAMES:0:-2}
fi
local PROFILE_OUTPUT="
------------------- [ ${USER_ID} ] ---------------------
User: ${FULL_NAME:-[unnamed]} (${USER_NAME})
Primary Group: ${PRIMARY_GROUP_NAME} (${PRIMARY_GID})
Other Groups: ${OTHER_GROUP_NAMES:-[none]}
----------------------------------------------$(printf -- '-%.0s' $(seq 1 ${#USER_ID}))
"
echo "${PROFILE_OUTPUT}"
}
USER_ID=${1}
if ! [[ "${USER_ID}" =~ ^[0-9]+$ ]] || ! id -nu "${USER_ID}" > /dev/null; then
>&2 echo "Please provide a valid UID as the first argument."
exit 1
fi
print_profile_for_uid ${USER_ID}
You will need to gather information from the Linux password (user) file, as well as the group file, likely with a combination of cat, grep, and cut piped together—read the man page for each. If you are not yet comfortable with Bash scripting, the Linux Documentation Project maintains an extensive guide, with sections on variables, conditionals and branching, functions, and debugging.
You should test your completed script against several UIDs. For example, the correct output when given UID 1003 on the VM is the following:
Submit your completed Bash script in full with your code package as a-1-profile.sh.
stat command to examine ugo permissions for the following questions.
/A1/Perms/File1, briefly describe what actions are allowed / disallowed, by whom./A1/Perms/Directory1, briefly describe what actions are allowed / disallowed, by whom.echo command. For example, to write to /A1/Perms/File1, use echo "Hello World!" >> /A1/Perms/File1 as your command.
/A1/Perms/File2. Refer to the ugo permission model to briefly explain what happens./A1/Perms/File3. Refer to the ugo permission model to briefly explain what happens./A1/Perms/SecretFile, owned by user bwayne. You do not have the ability to read or write to this file, but bwayne wishes to grant you this access by running chmod 666 /A1/Perms/SecretFile. From a security perspective, what is the disadvantage of doing this? What could you recommend they do instead, and why?ls -l command to list the contents of a directory, if necessary.
/A1/Perms/SecretStash. It has octal permissions 0770. (Use stat to confirm this.) Suppose your goal is to make this directory and all subdirectories readable and path-accessible to all users, and to do so, you use the command chmod -R 775 /A1/Perms/SecretStash. What negative side-effect will occur? Propose a different chmod command to mitigate this side-effect, and explain why it does.
/A1/Perms/SecretStash folder as a backup, and try out the provided command for yourself./A1/Perms/SecretSums has attempted to protect against other users reading the contents of the files listed in it by running the command: chmod o-r /A1/Perms/SecretSums. Explain why this was insufficient to achieve the intended security goal, and how your student user could circumvent this measure.
sudo to peek at the directory contents./usr/bin directory to find binary files that have their setuid bit set, using the find command. (Refer to its man page to help you with this.) Explain what behaviour the setuid bit enables for these binaries. Then, select one of the binaries you found, and justify why it needed this bit set.Relevant textbook sections: 5.4, 5.6, 6.1, 6.7
In this part, you will learn to exploit a classic time of check to time of use (TOCTOU) vulnerability in order to gain elevated privileges on your VM.
A sample vulnerable application is available on your VM in the /A1/Racing directory. It aims to write user-provided messages to a debug file when called. If the calling user lacks write permissions on this file, it will report an error and exit without writing. The time between it having checked the caller permissions and writing to the debug file is its vulnerability period. Your goal is to use this period to force it to write to arbitrary files for which you do not have write permissions. You will start by exploiting this vulnerability manually using a slow version of the application, and then move on to the fast version.
0 Marks /A1/Racing/Slow provides the vulnerable application in its "slow" form, vuln_slow. To help you understand how to exploit the race condition, this version pauses its execution during its vulnerability period, giving you time to manually perform the exploit. Calling vuln_slow requires two arguments: an integer for the number of seconds to pause execution, and the message you wish to write to the debug file.
In this directory, you will also find the file root_file. It is owned by the root user and has no write permissions for any other user. Your objective is to trick vuln_slow into writing a message to root_file, instead of its usual debug file. To do this, you will use a second terminal to replace the debug file with a symbolic link pointing to root_file, at the appropriate time.
Some notes to get you started:
vuln_slow application does not tell you where its debug file is. You can use the strace command to inspect what system calls it makes while it runs, which will give you an answer. Once you've found the debug file, open it to confirm that your message was in fact appended to it.ln command to create your symbolic link. Do not create a hard link. Read its man page for usage details.vuln_slow can be as large as you need to manually create your symbolic link.sudo command! Your goal is to elevate your own regular (non-root) user privileges by using an exploit.
If you've correctly performed the TOCTOU exploit, you should find your message appended to the end of root_file. Congratulations! Once you are successful, try it once again. What's different this time?
This question is unmarked, so you do not need to submit anything; however, as you soon will be performing this exploit in a more realistic manner, be sure to write down how the exploit process works from your understanding, step-by-step, including the commands you ran.
26 Marks Now that you have successfully executed this proof-of-concept TOCTOU exploit, you will repeat it in a real setting on your VM. You will find the same vulnerable application in the /A1/Racing/Fast directory, but it is now named vuln_fast and no longer accepts a pause argument. This makes its vulnerability period orders of magnitude shorter, which means that the exploit must be executed quickly, and with some luck, at the right time, for it to succeed. You will need to automate the exploit and attempt it multiple times to be successful.
In addition, the file that you will target this time is the root user's .rhosts file. (See the Ubuntu Manuals documentation on this file.) This is a configuration for a highly insecure set of remote access commands known as Berkeley r-utilities, which includes rsh and rlogin, precursors to the ssh command. (We will discuss these in greater detail later in the course, in Chapter 10.) These utilities are no longer typically enabled on modern systems, but your VM is configured to allow their use. The .rhosts configuration file is particularly compromising—when it is present in a user's home directory, such as /root/.rhosts, Berkeley r-utilities will read it and allow passwordless login for any user named within it! This makes it a valuable target to exploit.
You will attempt to add your student user to this file, gaining the ability to spawn a root shell using rsh. Write two Bash scripts for this question: b-2-runner.sh and b-2-exploit.sh:
vuln_fast infinitely until your exploit is successful—Bash has a few looping constructs to accomplish this.nice command to run vuln_fast with a high niceness value. (Why does this help?)vuln_fast to write—you want to log in as root from your user account.
ln command succeeds in creating the symbolic link. If you see it throw a lot of errors, there's an additional parameter you can provide it to force it to succeed...Open three terminals on your VM. In your first, use the watch command to run rsh -l root localhost whoami periodically—this tests to see if you have passwordless access to the root account. Then, run b-2-runner.sh and b-2-exploit.sh in your second and third terminals, respectively. If you've scripted everything correctly, it may take around 15 seconds for one of your attempts to succeed. If it did, congratulations, your user student has gained superuser privileges!
Include your scripts, b-2-runner.sh and b-2-exploit.sh, in your code package. In your report, describe the exploit in detail. You must include:
vuln_fast to do this.vuln_fast and your exploit script, line up to trigger a successful exploitation? Make sure to explain any command you wrote (and any options you invoked).