CS155: Computer and Network Security

CS155: Homework #1

Spring 2019

Due: Thursday, Apr. 25, 11:59pm

Problem 1: jump-oriented programming

Elizabeth is attacking a buggy application. She has found a vulnerability that allows her to control the values of the registers ecx, edx, and eip, and also allows her to control the contents of memory locations 0x9000 to 0x9014. She wants to use return-oriented programming, but discovers that the application was compiled without any ret instructions! Nonetheless, by analyzing the application, she learns that the application has the following code fragments (gadgets) in memory:

0x3000: add edx, 4      ; edx = edx + 4
        jmp [edx]       ; jump to *edx

0x4000: add edx, 4      ; edx = edx + 4
        mov eax, [edx]  ; eax = *edx
        jmp ecx         ; jump to ecx

0x5000: mov ebx, eax    ; ebx = eax
        jmp ecx         ; jump to ecx

0x6000: mov [eax], ebx  ; *eax = ebx
        ...             ; don't worry about what happens after this

Show how Elizabeth can set the values of the registers and memory so that the vulnerable application writes the value 0x2222 to memory address 0x8888.

Recall that eip is the instruction pointer. It holds the address of the next instruction to execute. ecx and edx are general purpose registers.

Problem 2: debugging a setuid root program

When running a setuid root program under the GDB debugger, the program does not run with root privileges. Consider a patch to the Linux kernel that makes it so that if a user debugs a setuid root program with GDB, the program being debugged runs with root privileges. Is this safe? If so, explain why. If not, describe an attack that is made possible by this change.

Problem 3: memory management

The iOS   _MALLOC(size_t size, int type, int flags) function allocates size bytes on the heap. Internally blocks are represented as a length field followed by a data field:

    struct _mhead {
      size_t  mlen;
      char    dat[0];  }
The mlen field is used by the free() function to determine how much space needs to be freed. In iOS 4.x the _MALLOC function was implemented as follows:
1   void * _MALLOC(size_t size, int type, int flags)  {
2     struct _mhead  *hdr;
3     size_t memsize = sizeof (*hdr) + size;
4     hdr = (void *)kalloc(memsize);  // allocate memory
5     hdr->mlen = memsize;
6     return  (hdr->dat);
7   }
In iOS 5.x the following two lines were added after line 3:
    int o = memsize < size ? 1 : 0;
    if (o)  return (NULL);
Why were these lines added in iOS5.x? Briefly describe an attack that may be possible without these lines.

Problem 4: Unix access control

In Unix, every process has a real user id (ruid), an effective user id (euid), and a saved user id (suid). Processes with an euid of 0 have special root privileges.
  1. If a process with user id n forks to create another process, what three user ids does the new process have? (Hint: it's the same answer for euid, ruid, and suid.)
  2. If a process with euid n makes a setuid system call, what possible euids can the process run with after the call, in each of the following situations:
    1. Before: euid = n > 0, saved user id suid=m and real user id ruid = m. After:?
    2. Before: n=0 After:?
  3. The Linux login process runs and starts new processes as root. After forking to create a new process, setuid is called. What three UIDs does the forked process have after calling setuid? Why is it important that the process calls setuid and not seteuid? How could you exploit your shell if seteuid had instead been called?
  4. Many Linux distributions use capabilities instead of setuid for elevating the privileges of system utilities. For example, the ping utility has the following capabilities: /usr/bin/ping = cap_net_raw+ep.
    1. What benefits do capabilities have over setuid? Assuming the ping utility has an exploitable buffer overflow vulnerability, what's an attack that is blocked by its current capabilities that would have been possible had setuid had been used?
    2. If the ping utility used setuid instead of capabilities, what user should own the executable? Why is it important which user owns it? Assuming all users should be able to execute ping, what file permissions should other have to the executable?
  5. In Android, each Android application runs in a separate process using a separate user id. From a security standpoint, what is the advantage of assigning separate uids instead of using the same uid for all? Explain.

Problem 5: 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" );         // open file for write
  fprintf(fp, "Hello world" );
  1. 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. Hint: try using symbolic links.
  2. Suppose the sleep(10) is removed from the code above. Could the problem you identified in part (a) still occur? Please explain.
  3. How would you fix the code to prevent the problem from part (a)?