Preparation: On the host, run as root ```sh echo 0 > /proc/sys/fs/protected_symlinks ``` Start the myUnix environment, enter as root and start `rshd`. Make sure that there is no `/.rhosts` file before trying every exercise (remove it otherwise). Use `passwd` to set a password for the root user. You can then logout root and login as, e.g., user1. Assume the user has no root privilege and doesn't know the root password. bad4suid ======== This suid-root program creates a temporary file named `/tmp/tmpfile` using `fopen()` with `"w"` mode. This mode will create the file if it does not exist, and also follow any symbolic link in the path. The idea is to abuse this program to create a `/.rhosts` file that is writeable by the attacker. Once the file has been created, the attacker can write the IP address of any machine she owns (or the `+` wildcard) and then connect remotely from that machine to the root account without having to guess the root password. First, the attacker creates a symbolic link to `/.rhosts`: ```sh ln -s /.rhosts /tmp/tmpfile ``` When the suid-root program will be run, the `fopen()` in the program will create the `/.rhosts` file. The `fopen()` function passes mode 0666 to the `open()` system call, asking for read and write permission for everybody (owner, group and others). The kernel, however, will remove the permissions found in the process' umask. This is not a problem for the attacker, since the process will inherit the umask from the attacker's shell: the attacker can simply reset her own umask to 0 before running the vulnerable program: ```sh umask 0 bad4suid ``` Now the `/.rhosts` file has been created with write permission for everybody, and the attacker can therefore write into it: ```sh echo + > /.rhosts ``` Then, she can connect from any remote machine. In our setup, we can connect from the host: open a new terminal, navigate to the myUnix directory and type ```sh util/rsh ``` Then answer `root` to the `login:` prompt. The `rshd` server will let you enter without asking for a password. bad5suid ======== This is just like `bad4suid`, but the programmer has tried to create a temporary file with a name which is harder to guess, since it includes the pid of the current process. Pids, however, are assigned sequentially, and therefore are easily guessed. Assume, for example, that nobody else is using the sytem besides the user1 attacker. Then user1 can run, e.g., ```sh ps ``` and note the pid of the `ps` process itself. Assume it is 15. Then she can type ```sh ln -s /.rhosts /tmp/tmpfile.17 umask 0 bad5suid ``` In fact, the `ln` command will be executed by process 16, `umask` is an internal command that will be executed by the shell without creating any new process, and therefore `bad5suid` will be executed by process 17. Even if other processes are beeing created concurrently by other users, the problem becomes only slightly more difficult for user1: she can just try again if the guessed pid was wrong, and she can also create more than one symbolic link to allow for a range of possibile pids. bad6suid ======== Here the programmer has tried to create `/tmp/tmpfile` only if it doesn't already exist. The program, however, contains a Time-Of-Check-to-Time-Of-Use (TOCTUI) problem: since the check and the file creation are performed in two distinct system calls, the check/creation combination is not atomic and the attacker may create the link between the check and the `fopen()`. In this case the exercise is simplified by the presence of the `sleep()` between the two actions, which makes the attack very likely to succeed: ```sh umask 0 bad6suid & ln -s /.rhosts /tmp/tmpfile ``` We create two processes, one running `bad4suid` and another running the `ln` command, and we let them run concurrently (with the `&` character). The `bad6suid` process will very likely run first (since the myUnix shell creates it before the other one) and will perform the check successfully; then it will go to sleep, and the kernel will schedule `ln`, which creates the link; when the sleep time elapses, the kernel will run `bad6suid` again, which will `fopen() the symlink. Note that the `sleep()` is not necessary for this kind of attack to succeed. The attacker can just try repeatedly with something like ```sh while ! [ -e /.rhosts ]; do bad6suid & ln -s /.rhosts /tmp/tmpfile rm /tmp/tmpfile done ``` The myUnix shell, however, doesn't support the `while` construct.