Midterm1 2

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

I.

Set-UID
1. Alice runs a Set-UID program that is owned by Bob. The program
tries to read from /tmp/x, which is readable to Alice, but not to
anybody else. Can this program successfully read from the file?
No. The Set-UID program owned by Bob will try to read /tmp/x
as Bob, and not Alice. And since only Alice can access that
file, the program cannot.
2. A process tries to open a file for read. The process's effective user
ID is 1000, and real user ID is 2000. The file is readable to user ID
2000, but not to user ID 1000. Can this process successfully open
the file? No. Since the effective user ID doesn't have access to
the file, the process cannot open it.
3. A root-owned Set-UID program allows a normal user to gain the
root privilege while executing the program. What prevents the user
from doing bad things using the privilege? Good programming
practices while writing the set-uid program. By not mixing
user input with trusted data, and not using vulnerable APIs
such as system, the root program will be very limited in scope
as to what it can do.
4. We are trying to turn a program prog owned by the seed user into
a Set-UID program that is owned by root. Can running the
following commands achieve the goal?
$ sudo chmod 4755 prog
$ sudo chown root prog
The first command sets the Set-UID bit on the program by
using the chmod command with the numeric value 4755. This
value sets the Set-UID bit and ensures that the program runs
with the privileges of the owner (root) when executed.

The second command changes the ownership of the program


to root using the chown command. This ensures that the
program is owned by root and not the original owner (seed
user).

After running these two commands, the program prog is now


a Set-UID program that is owned by root. This means that
when the program is executed by any user, it will run with
root privileges.
5. The chown command automatically disables the Set-UID bit, when
it changes the owner of a Set-UID program. Please explain why it
does that. The Set-UID bit is a file system attribute that allows
a user to execute a program with the permissions of the file's
owner, rather than their own.
This feature is useful for programs that require elevated
privileges to run, such as system management tools or
password-changing utilities.
However, the Set-UID bit can also be a security vulnerability if
not handled properly.
When the owner of a Set-UID program is changed using the
chown command, the Set-UID bit is automatically disabled for
security reasons.
This is because the Set-UID bit can allow users to execute
code with elevated privileges, which can be exploited by
malicious actors.
Disabling the Set-UID bit when the owner of a Set-UID
program is changed helps prevent unauthorized access to
sensitive system resources.
For example, a malicious user could change the ownership of
a Set-UID program to their own user account, gaining
unauthorized access to sensitive system resources.
By disabling the Set-UID bit, the chown command ensures
that the program can only be executed with the intended
permissions.
Overall, the automatic disabling of the Set-UID bit by the
chown command when the owner of a Set-UID program is
changed helps to prevent security vulnerabilities and ensure
the proper execution of these programs.
6. When we debug a program, we can change the program's internal
variables during the execution. This can change a program's
behavior. Can we use this technique to debug a Set-UID program
and change its behavior? For example, if the program is supposed
to open the /tmp/xyz file, we can modify the filename string, so the
Set-UID program ends up opening /etc/passwd. When a
program is being debugged, it is indeed possible to modify its
internal variables during execution, and this can change the
program's behavior. However, when it comes to a Set-UID
program, there are additional security restrictions in place to
prevent unauthorized access.

In a Set-UID program, the program runs with the privileges of


the file owner, not the user who executes the program. This is
a powerful mechanism that allows users to perform tasks that
require certain permissions, all while maintaining a secure
system.

Modifying the behavior of a Set-UID program during execution


can be challenging, and it is not a recommended practice.
This is because it could lead to unexpected and potentially
harmful behavior. For example, if the program is intended to
open a file in the /tmp directory, and you modify the filename
string to open the /etc/passwd file instead, you could
potentially expose sensitive system information.

To clarify, the specific example you mentioned is not


recommended and could result in security risks, especially
when dealing with privileged files such as /etc/passwd. It is
important to maintain the integrity of the system and follow
best practices when debugging programs, especially those
that have elevated privileges like Set-UID programs.
7. Both system() and execve() can be used to execute external
programs. Why is system() unsafe while execve() is safe? The
system() function can be considered unsafe compared to execve()
because system() invokes a shell interpreter to execute the command,
while execve() does not. This difference can expose system() to
command injection attacks, where an attacker can inject malicious
commands into the input string, which can then be executed by the
shell interpreter.

In contrast, execve() directly replaces the current process image with


a new process image, without invoking a shell interpreter. This
makes it more secure, as there is no risk of command injection
attacks.

8. When a program takes an input from users, we can redirect the


input device, so the program can take the input from a file. For
example, we can use prog < myfile to provide the data from myfile
as input to the prog program. Now, if prog is a root-owned Set-UID
program, can we use the following method to to get this privileged
program to read from the /etc/shadow file?
$ prog < /etc/shadow
No, you cannot use the method prog < /etc/shadow to get the privileged
program prog to read the /etc/shadow file, even if prog is a root-owned Set-
UID program.

When you run the command prog < /etc/shadow, the shell creates a new file
descriptor (in this case, standard input) that is connected to the /etc/shadow
file, and the program prog reads from that file descriptor as if it was
reading from the terminal.

However, in the case of a Set-UID program, the program runs with the
privileges of the file owner (in this case, the root user), but it does not run
as the root user. Therefore, the program is not allowed to access files
outside of the permitted directories, even if the file is specified as a file
descriptor through standard input.

In other words, the program prog can only access the /etc/shadow file if it is
explicitly opened by the program using the appropriate file I/O functions
(such as open()), and not through the file descriptor provided by the shell.
Therefore, the command prog < /etc/shadow is not a security risk to the
/etc/shadow file, even if prog is a privileged program.
Is this conversation helpful so far?
dịch câu trả lời vừa rồi sang tiếng việt
No, you cannot use the method prog < /etc/shadow to get the privileged
program prog to read the /etc/shadow file, even if prog is a root-owned Set-
UID program.

When you run the command prog < /etc/shadow, the shell creates a new file
descriptor (in this case, standard input) that is connected to the /etc/shadow
file, and the program prog reads from that file descriptor as if it was
reading from the terminal.

However, in the case of a Set-UID program, the program runs with the
privileges of the file owner (in this case, the root user), but it does not run
as the root user. Therefore, the program is not allowed to access files
outside of the permitted directories, even if the file is specified as a file
descriptor through standard input.

In other words, the program prog can only access the /etc/shadow file if it is
explicitly opened by the program using the appropriate file I/O functions
(such as open()), and not through the file descriptor provided by the shell.

Therefore, the command prog < /etc/shadow is not a security risk to the
/etc/shadow file, even if prog is a privileged program.

9. When a parent Set-UID process (effective user ID is root, and the


real user ID is bob) creates a child process using fork(), the
standard input, output, and error devices of the parent will be
inherited by the child. If the child process drops its root privilege, it
still retains the access right to these devices. This seems to be a
capability leaking, similar to what we covered in Chapter 1.4.4.
Can this pose any danger? In the scenario you have described, a
parent Set-UID process with root effective user ID and bob real user
ID creates a child process using fork(). The child process inherits the
standard input, output, and error devices of the parent. If the child
process drops its root privilege, it still retains access to these
inherited devices.

However, this does not necessarily pose a danger, as the child process
is not directly accessing the /etc/shadow file or other sensitive
resources. The risk of capability leaking only becomes a concern if
the child process passes these access rights to another process, or if
the child process itself is vulnerable to attacks that exploit these
access rights.

In general, it's a good practice to minimize the attack surface of a


program by dropping unnecessary privileges as soon as possible. This
can help prevent capability leaking and other types of vulnerabilities.

II. Environment Variables

1. What is the difference between environment variables and shell


variables? Environment Variables:
a. Definition: Environment variables are system-wide variables that are
inherited by all system processes and shells.
b. Scope: They apply globally and persist across different programs and
sessions.
c. Storage: Managed by your shell, they are stored in memory and
accessible to any program you start.
d. Examples: Variables like PATH, HOME, and LANG are environment
variables.
e. Notation: By convention, environment variables use UPPER CASE
names.
f. Setting: You can set environment variables in files like ~/.bashrc or
through system-wide configuration.
Shell Variables:
g. Definition: Shell variables are specific to the current instance of the
shell (such as a shell script) and are not inherited by child processes.
h. Scope: They are local to the shell where they are set.
i. Storage: Contained exclusively within the shell, they don’t propagate to
other programs.
j. Examples: Variables you define during a shell session.
k. Notation: Shell variables use lower case names.
l. Setting: You can set shell variables directly in the shell using
assignments like MY_VAR=value.
In summary, environment variables have a broader reach and persist throughout a
session, while shell variables are specific to the current shell instance and don’t
propagate to child processes.

2. In Bash, if we run "export foo=bar", does it change the


environment variable of the current process? No, running export
foo=barin Bash does not change the environment variable of the current
process. Instead, it creates a new environment variable called foo with a
value of bar for the current process and propagates this variable to any
subsequent child processes.
3. The followings are two different ways to print out environment
variables. Please describe their differences:

$ /usr/bin/env

$ /usr/bin/strings /proc/$$/environ
The /usr/bin/env and /usr/bin/strings /proc/$$/environ
commands are used for different purposes when working with environment variables
in a Linux environment.

/usr/bin/env is used to execute a command in an environment modified by the

variables specified on the command line. It's useful when you want to run commands
with a specific environment, like a particular version of a programming language or
interpreter. If used without any additional arguments, env will print the current
environment variables for the user.

On the other hand, /usr/bin/strings /proc/$$/environ is used to get the


environment variables directly from the current running process (in this case, $$
expands to the process ID of the current shell). It's more of a low-level way to access
environment variables, and it's useful for debugging or accessing the current
environment variables without using the shell built-in export or the printenv
command.
Summary:

env is a command to run commands with a modified environment or to display


current environment variables;

strings /proc/$$/environ is a low-level way to access environment


variables directly from the current process.

4. In our code, when we use execve() to execute an external program


xyz , we pass NULL in the third argument. How many environment
variables will the process running xyz has? When execve() is called
with NULL as the third argument, the new process running the
external program xyz will inherit the environment variables from
the calling process. This means that the number of environment
variables will be the same as in the parent process.

The count of environment variables depends on the


environment and configuration of the parent process, and it is
not directly affected by the execve() call or the NULL argument.
It is important to note that the new process has its own copies
of the environment variables; modifying the environment
variables in the child process will not affect the environment
variables in the parent process.

To summarize, the number of environment variables in the


process running xyz depends on the environment of the
parent process and cannot be directly determined from the
execve() function call.

5. Bob says that he never uses any environment variable in his code,
so he does not need to worry about any security problem caused
by environment variables. Is he correct?
No, Bob is not entirely correct. While Bob may not use environment variables directly
in his code, it's still possible for his code to be impacted by security issues related to
environment variables. I can illustrate the potential risks with the PATH and
LD_LIBRARY environment variables.

The PATH environment variable tells the system where to look for executable files. If
an attacker manages to modify Bob's PATH variable, they could potentially replace a
legitimate program with a malicious one. As a consequence, when Bob's code runs
the legitimate program, the malicious one might be executed instead. So, even
though Bob does not use any environment variables directly in his code, it's
important to be aware of the security issues related to environment variables and to
take appropriate precautions to protect the environment. Keeping the environment
variables clean, and limiting the permissions of environment variables, can help
prevent such security issues.

6. A program abc invokes an external program xyz using system(),


which is affected by the PATH environment variable. When we
invoke abc from a shell prompt, how does the shell variable PATH
in the current shell end up affecting the behavior of the system()
function?

The PATH environment variable in the current shell will impact the behavior of
the system() function in two primary ways:

Identifying the executable: When abc calls the system() function trying
to execute xyz, the system will first look at the directories mentioned in
the PATH variable to locate the xyz program. This means that the content
of the PATH variable in the current shell determines the actual executable
file that gets loaded.

Searching for the program: If xyz is not present in the standard


directories (such as /usr/bin, /bin, and /usr/local/bin), the system()
function, following the PATH environment variable, may end up executing
a different file named xyz, if another program with the same name exists
in one of the directories specified in the PATH variable.
In summary, the behavior of system() in abc code will depend on the PATH
environment variable in the current shell, as it will determine the exact file
executed and search paths for the program.

7. Please explain why using secure getenv() is better than using


getenv().
getenv():

a. The getenv() function is commonly used to retrieve the value of an


environment variable.
b. It searches the environment list for the specified environment variable
name and returns a pointer to the corresponding value string.
c. However, it lacks security checks and may not be suitable for all
scenarios.

secure_getenv():

d. The secure_getenv() function is a GNU-specific extension.


e. It behaves similarly to getenv(), but with an important distinction: it
returns NULL in cases where “secure execution” is required.
f. Secure execution is necessary under specific conditions:
i. When the program was loaded with mismatched effective
user/group IDs (e.g., due to set-user-ID or set-group-ID
programs).
ii. If the executable file has the effective capability bit set.
iii. When the process has a nonempty permitted capability set.
iv. It may also be triggered by certain Linux security modules.
g. The primary purpose of secure_getenv() is to prevent
vulnerabilities that could arise if set-user-ID or set-group-ID programs
blindly trusted environment variables.

Advantages of secure_getenv():

h. Security: By returning NULL when secure execution is required, it helps


prevent unintended security risks.
i. Avoiding Trust in Environment Variables: Libraries and security-critical
code can use secure_getenv() to avoid trusting potentially unsafe
environment variables.
j. Best Practice: It’s recommended for general-purpose libraries to use
secure_getenv() to enhance security.

In summary, while getenv() is straightforward for basic environment variable


retrieval, secure_getenv() provides an extra layer of security by refusing to return
values in certain critical scenarios. Therefore, when security matters, favor
secure_getenv() over getenv()

8. A privileged Set-UID program needs to find out which directory it is


currently in. There are two typical approaches. One is to use the
PWD environment variable, which contains the full path of the
current directory. Another approach is to use the getcwd() function
(you can find its manual online). Please describe which approach
you would like to take and why.

I would recommend using the getcwd() function. The reason


is that getcwd() returns the absolute path of the current
working directory, while the PWD environment variable may
not always resolve symlinks to their original paths.

In the context of a privileged Set-UID program, security is a


significant concern. If the program needs to access sensitive
files or directories, it is crucial to ensure that it is working in
the correct location. Using the getcwd() function reduces the
risk of errors or potential security vulnerabilities that could
arise from symlinks or unexpected changes to the PWD
environment variable.

Additionally, getcwd() is a standard C function that is widely


supported across different operating systems, making it a
more portable option than the PWD environment variable. By
using getcwd(), you can be more confident that your program
will behave consistently across different environments.

Overall, while both the PWD environment variable and the


getcwd() function can be used to determine the current
working directory, I would recommend using the getcwd()
function for its accuracy, consistency, and portability.

9. In Linux, many environment variables are ignored by the dynamic


linker if the program to be executed is a Set-UID program. Two
such examples are LD_PRELOAD and LD_LIBRARY PATH.
Please read the manual of ld-linux (https://linux.die.net/man/8/ld-
linux) and explain why the following environment variables are also
ignored:

· LD_AUDIT

· LD_DEBUG_OUTPUT.

LD_AUDIT

The LD_AUDIT environment variable allows you to specify an audit


program that is executed whenever a library is loaded by the
dynamic linker. The audit program is passed information about the
library that is being loaded, and it can choose to permit or deny the
loading of the library.

However, when the program to be executed is a Set-UID program,


the LD_AUDIT environment variable is ignored by the dynamic
linker. This is because Set-UID programs are designed to run with
the privileges of the owner of the program, rather than the
privileges of the user who is running the program. Allowing the
user to specify an audit program could be a security vulnerability,
as it could allow the user to interfere with the execution of the
program in unintended ways.

LD_DEBUG_OUTPUT

The LD_DEBUG_OUTPUT environment variable allows you to


specify a file to which the dynamic linker should write debugging
information. This can be useful for debugging problems with the
dynamic linker.

However, when the program to be executed is a Set-UID program,


the LD_DEBUG_OUTPUT environment variable is ignored by the
dynamic linker. This is because writing debugging information to a
file could be a security vulnerability, as it could potentially reveal
sensitive information about the program or the system.
In general, the dynamic linker ignores many environment variables
when the program to be executed is a Set-UID program. This is
because Set-UID programs are designed to run with the privileges
of the owner of the program, rather than the privileges of the user
who is running the program. Allowing the user to specify
environment variables that affect the behavior of the dynamic linker
could be a security vulnerability, as it could allow the user to
interfere with the execution of the program in unintended ways.

10. There are two typical approaches for letting normal users do
privileged tasks, one is to write a root-owned Set-UID program,
and let the user run; another approach is to use a dedicated root
daemon to do those privileged tasks for users. Please compare the
attack surfaces of these two approaches, and describe which one
is more secure.

Both approaches have their own potential attack surfaces, and the
choice between them depends on the specific use case.

A root-owned Set-UID program, when executed by a normal user,


runs with the privileges of the owner (in this case, root), allowing
the user to perform privileged tasks. The attack surface here is
primarily the Set-UID program itself. If there are bugs or
vulnerabilities in the program, an attacker could potentially exploit
them to gain root access. Therefore, the program needs to be
carefully written and audited to ensure its security.

On the other hand, a dedicated root daemon is a system service


that runs continuously in the background, listening for requests
from normal users. When it receives a request, it performs the
privileged task on behalf of the user. The attack surface here is the
daemon itself and its communication channels. If the daemon has
vulnerabilities, an attacker could exploit them to gain control of the
daemon or intercept communications to it. Furthermore, the
channels through which users communicate with the daemon (e.g.,
network sockets, system calls) need to be secured to prevent
unauthorized access or eavesdropping.
In general, both approaches can be made secure with proper
design and implementation. However, the root daemon approach
might be considered more secure because it isolates the privileged
code in a separate process, reducing the attack surface of the
user's session. Additionally, the root daemon can implement
additional access controls and auditing, providing an extra layer of
security.

You might also like