University of Minnesota
Development of Secure Software Systems

CSci 4271 Lab 4

The new material for the first half of today's lab will give you hands on experience with Unix file permissions, continuing the abstract discussion from lecture. We suggest you use the second half of the lab to continue or review material from the last couple of labs related to attacks, since these concepts will be relevant to the upcoming Project 1.

In the online lab we'll randomly split you into breakout groups of 2-3 students: please work together, discuss, and learn from the other student(s) in you group. Use the "Ask for Help" button to ask questions or show off what you've done.

  1. (Hands-on with Unix permissions)

    For the first part of the lab, we'd like you to spend some time trying out Unix commands related to checking and changing the permissions on files. In the description below we'll first introduce some permissions-related commands; then we'll give some suggestions of things you can try out.

    Since you're doing the lab with other students, you should take advantage of being able to ask another student to test an operation for you. One of the limitations of trying out file permissions yourself is that you can only simulate one user's accesses, but someone else can check how permissions work for a non-owner.

    Your CSE Labs home directories are stored on a networked file systems where some rarer aspects of permissions are unsupported or work differently. You also might not want to change the permissions on your home directory to let another student access it, even temporarily. So what we recommend you use instead is creating files and directories inside the directory named /tmp that is explicitly for temporary files. Note however that the /tmp directory is not shared between machines, so multiple people doing testing should all SSH into the same machine to run experiments in its /tmp. Also, the top-level directory /tmp has some special rules, so create a subdirectory of /tmp for testing.

    There are three commands we recommend you try out for looking at the permissions on Unix files (all of these commands also have more detailed documentation in their man pages):

    • The most commonly used program is ls with the -l (lowercase ell for long) option that causes it to print a line of information about each file or directory. The permissions information is in the 2nd through 10th columns, after the very first column which gives the file type. These columns mostly correspond to the nine basic permissions bits, where they are either a hyphen to represent a bit being 0, or an r, w, or x to represent a one bit based on its position. There is an exception that an x bit will turn into an s, S, t, or T in some special circumstances we haven't covered yet. Later in the line you'll see the names of the user and group owners.

    • The stat command-line program is like a more detailed version of ls -l that prints all of the metadata returned by the stat system call, across several lines. The line of its output that has the headings Access:, Uid:, and Gid: has the permissions information. The most useful extra feature for us is that it prints the octal version of the permissions bits.

    • The command getfacl provides the most expanded version of the permissions information; as the letters ACL in its name indicates, the multiple lines of its output have the structure of a general access-control list. You may find its output the easiest to read; it also become important once you try out more general ACLs (described later).

    Then there are two commands you can try out to change permissions on files:

    • The command chgrp has a limited purpose: it changes the group of a file. Only the owner of a file can change its group, and they can only change it to another group they are a member of. You can use the command groups to see what groups you're a member of. There is also an analogous program named chown to change the owner of a file, but it is useless to you on CSE Labs machines because only root can change the ownership of files. (Actually, chown can change just the group; then it's equivalent to chgrp.)

      The command chmod changes permissions. The most basic way to use it, which is convenient if you know exactly the permissions you want in octal, is to use the new permissions in octal as the first argument, and any remaining arguments are the names of files or directories you want to have that permission set. If you want to change some of the permissions and leave others the same, which is most important if your changing multiples files at once, the first argument also has a letter-based form that you can read about in the manual page. And if you want to change the permissions on a whole tree of files, the option -R causes chmod to work recursively on a directory and all of the files and directories inside it.

    Take some time to try out these programs on different files, and then trying to do different operations on the files, to see whether the permissions work the way you would expect. For checking whether you can execute a file, you may want to work with a file that's a copy of a simple executable from a system directory, for instance /bin/uname. Once the basics seem to make sense, here are some further things you can try:

    • Try creating a directory where you have execute but not read permissions. For instance if you can access a file in that directory if you know its name, but ls and tab completion won't work.
    • Conversely, what happens if you try to run ls or ls -l on a directory for which you have read but not execute permission? Why?
    • If you have write permission but not execute permission on a directory, are there any operations you can do to it?
    • Suppose there is a file that you want to modify, and you don't have write permissions on the file, but you do have write permissions on the directory where the file is stored. What can you do?
    • Similar to the previous question, but what if the file is inside several levels of directories you don't have write access to, but high above it there is a directory you can modify?
    • The restriction of file ACLs having only one specified user and one specified group, which is traditional in Unix, has been lifted in many derived systems. The extension that's most reliably available for local filesystems on Linux is referred to as POSIX ACLs (though it never made it to an official part of the POSIX standard). You can set these with the command setfacl which is the modifying counterpart of the reading program getfacl mentioned above. The full mechanism has a number of wrinkles, but as something simple you might try giving read access to just one other person, something that in the traditional Unix model would require creating a new group.

    Here's one question you might think about as a bit of a brainteaser; it's related to Unix permissions bits but is more of a math (or CSci 2011) question. If we put no restrictions on the different bits in a permissions set, there are a total of 512 different possible permissions sets, but most of these are not very useful. One restriction you might imagine imposing to get a more limited but useful set of permissions is to require that the permissions never go down as you go to a more specific level. In other words, require that every permission that other users have, group users have, and every permission that group users have, the owner also has. For instance 000, 700, 777, 755, and 664 all obey this restriction, but 070 and 321 do not. How many permission sets remain after imposing this restriction? The best answer would be a formula for counting the permissions that generalizes to different numbers of permission bits or different numbers of levels, and an explanation of where the formula comes from.

  2. (Review of attack techniques)

    We recommend you spend the remaining time in lab returning to some questions you may have left unfinished from the last couple of labs related to attack techniques.

    • The second question of lab 2 illustrates an additional complexity in overflows that can make them harder to exploit, but which you can often work around.
    • The BCLPR program from lab 3 also has a format string vulnerability, as we saw in lecture. Can you finish the process of constructing an attack? To make it easier to exploit, we've made a slightly changed version of the program that you can use a slightly different command to compile. Specifically do the following:

      cp /web/classes/Spring-2021/csci4271/labs/04/bclpr.c .
      gcc -no-pie -z execstack -z norelro -g -Wall -Wno-format-security -fno-stack-protector bclpr.c -o bclpr

      You should set up the directories in /tmp in the same way as last week. This is a relatively complex attack, but you can build it up step by step:

      1. First, use the vulnerability just for information disclosure. You should be able to dump a lot of different contents of the stack in this way.
      2. Comparing the stack dump with the local variables of the function with the vulnerability, find and additional data area that you can control from outside the program. You can save yourself typing by creating the format string with a script, or by using the $ feature of printf.
      3. To get control, you'll want to use the vulnerability to overwrite a location that will be used as a jump target. Depending on how you're supplying the extra information, a return address on the stack may be out of reach, and it can also be hard to hit because of changing location. Another approach you can use takes advantage of how functions in a shared library are called. If you look instruction by instruction at what happens when a library function like fclose is called, you'll see there's a value that's similar to a function pointer that is used to find the location of the function in the library. Try using this as the location to overwrite.
      4. As a side effect of your attack, you may see that it's writing about 4MB of data in BCLPR's log file on each attempt. This is not so much as to keep the attack from working, but you might want to remove the log file periodically so it doesn't take too much space.