CS155: Computer and Network Security

CS155: Homework #1

Spring 2012

Due: Tuesday, May 1st


Problem 1: Control hijacking

(a) In x86 the stack grows downwards. Explain how a stack-based overflow attack would work if the stack grew upwards instead.

(b) How would you implement StackGuard in an architecture where the stack grows upwards? What would be different from StackGuard on the x86?

(c) How would you implement LibSafe in an architecture where the stack grows upwards? What would be different from LibSafe on the x86?

(d) Suppose you find a memory leak in a third-party library, e.g. the library cleanup function forgets to call free on a certain pointer p. You notice that some applications fix the problem by freeing the memory themselves. How could you fix the library cleanup function to free p without introducing a double-free vulnerability in applications that free the memory themselves? You are only allowed to change the library. If you need to make an assumption about how the free function works, make sure to state your assumption explicitly.


Problem 2: Overflows

A proposal for preventing stack buffer overflow attacks is based on making a backup copy of the return address when a function starts. The backup copy is written to a shadow stack located at some location L on the heap. When the function terminates the backup copy is copied to the appropriate place in the stack and then the function executes the return instruction.

(a) Explain why this mechanism can make it harder to mount a stack buffer overflow attack.

(b) Give sample code that is vulnerable to a stack buffer overflow even if this mechanism is used. Hint: first, try to expose L, then use L to mount the exploit.


Problem 3: Sandboxing

(a) Explain when would you use VM-based sanboxing rather than system call interposition.

(b) Explain when would you use system call interposition rather than VM-based sanboxing.

(c) In class we discussed a covert channel between two VMs based on CPU utilization and a synchronized clock between the VMs. One might try to block this covert channel by preventing the VMs from synchronizing their clocks, e.g. by presenting each VM with a different time of day. You may assume the clocks run at normal speed, but are shifted by a random amount for each VM. Explain how an attacker can defeat this defense.

(d) Suggest another method by which the covert channel based on CPU utilization can be blocked.


Problem 4: Unix access control

Part I Recall that RUID stands for “Real User ID”, EUID stands for “ Effective User ID”, and SUID stands for “Saved User ID”; recall also that programs can change their EUID (in restricted ways) by making the seteuid system call. Suppose that a Unix directory contains the following files with permissions set as shown. Assume that all SetGID and Sticky bits are turned off.

                File Description          Permissions
    Filename      Owner   Group    SetUID Owner Group Other
    a.txt          10     10         -    rw-   r--   ---
    b.txt          10     65         -    ---   rw-   rw-
    c.txt          45     45         -    rw-   -w-   ---
    d.txt          20     20         -    rw-   r--   r--
    app            20     65         y    --x   --x   ---
    server         20     45         -    --x   --x   ---

Assume that user 10 is in groups 10, 65, and 45. Assume that user 20 is only in group 20.

  1. Consider a process running with RUID=20, EUID=20, and SUID=20. Assuming no other process changes any of the file permissions, which of these files could it read?
  2. Consider a process running with RUID=10, EUID=10, and SUID=15. Assuming no other process changes any of the file permissions, which of these files could it write?
  3. Suppose a process running with RUID=0, EUID=0, and SUID=0 calls the exec system call to run the program "app". Assuming no other process changes any of the file permissions, which of these files could that instance of app read?
  4. Suppose a process running with RUID=10, EUID=10, and SUID=10 calls the exec system call to run the program "server". Assuming no other process changes any of the file permissions, which of these files could that instance of server execute?

Part II The Unix mount command attaches the filesystem found on some device to the file tree of the system executing the mount command. The standard form of the mount command, is

       mount -t type device dir
This tells the kernel to attach the filesystem found on device (which is of type type) at the directory dir. The previous contents (if any) and owner and mode of dir become invisible. As long as this filesystem remains mounted, the pathname dir refers to the root of the filesystem on device. The filename, owner, group and permissions of the files on the mounted device, including the SetUID bits, and Owner, Group, and Other permissions, are used by the system that mounts the device. Suppose a USB drive contains file f that has owner 0, execute permission, and SetUID bit set. If user 10 executes this file, which files above (a.txt, b.txt, c.txt , d.txt, app, server) will Unix let the program in file f access? Is this a security problem? The Unix mount command has two relevant options.
noexec     Do not allow direct execution of any binaries on the mounted filesystem. 

nosuid     Do not allow set-user-identifier or set-group-identifier bits to take effect. 
Which of these options would prevent the problem you discovered at the beginning of Part II? Which of these options seems more useful for mounting file systems that may contain useful programs? Why?

Problem 5: Code analysis

In lecture 5, we discussed taint analysis and one of the readings for that lecture discusses the tainted object propagation problem. Taint analysis is a general approach for finding many kinds of program bugs. In most forms of taint analysis, a value from an unknown or untrusted source is considered tainted. If the value is tested or manipulated in some way, then it may become untainted. If a tainted value is used an argument to a sensitive operation, then an error is reported. For example, PERL user input is considered tainted, and an error is reported if tainted values are used in system calls. If a tainted PERL value is compared to a pattern that is contained literally in the program, and not read from some other source, then it is considered untainted.

  1. Taint analysis can be used to find buffer overflow vulnerabilities in source code by disallowing tainted array indices. Explain why a value should be considered untainted only if there are checks to make sure it is bigger than some minimum value and smaller than some maximum value - it is not enough to just check that it is less than some maximum value. You may want to refer to the following Linux device driver code.
  2.     /* 2.4.5/drivers/char/drm/i810_dma.c */
        if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d)))
                return -EFAULT;
    
        if(d.idx > dma->buf_count) return -EINVAL;
        buf = dma->buflist[ d.idx ];
        buf_priv = buf->dev_private;
        if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
    
        if (copy_from_user(buf_priv->virtual, d.address, d.used))
                return -EFAULT;
  3. Taint analysis can be applied to source code, by simulated execution that keeps track of whether the values of variables could be tainted or not, or applied at run-time by keeping track (in an interpreter, for example) of whether the actual value is tainted. In a project for detecting malware via runtime taint analysis, researchers at CMU automatically insert taint tracking instructions. For example, the following code
         recv(socketfd, buf1, …);
         memcpy(buf2, buf1, …);
         y = x;
         strcpy(dummy->buf, buf1);
         dummy->fnptr();
    
    is instrumented by inserting the indented lines
         recv(socketfd, buf1, …);
              NewTaint(buf1, …);
         memcpy(buf2, buf1, …);
              PropTaint(buf2, buf1, …);
         y = x;
              PropTaint(&y, &x, …);
         strcpy(dummy->buf, buf1);
              PropTaint(dummy->buf, buf1, …);
              TaintAssert(&fnptr, …);
         dummy->fnptr();
    
    The first function call creates a new taint tracking flag for buf1. The next call sets the taint flag for buf2 to the flag value for buf1, and so on. The TaintAssert function makes sure that the taint flag for the given argument does not indicate that the value is tainted. If TaintAssert is called with a tainted argument, and error is reported. Explain the error in this code and how tainting analysis catches it.

Problem 6: race-conditions

Consider the following code snippet:
  if (!stat("./file.dat", buf)) return;   // Abort if file exists.
  sleep(10);                              // Sleep for 10 seconds.
  fp = fopen("./file.dat", "w" );
  fprintf(fp, "Hello world" );
  close(fp);

(a) Suppose this code is running as a setuid root program. Give an example of how this code can lead to unexpected behavior that could cause a security problem. (try using symbolic links.)

(b) Suppose the sleep(10) is removed from the code above. Could the problem you identified in part (a) still occur? Please explain.

(c) How would you fix the code to prevent the problem from part (a)?