CSE 409/509 Spring 2009. Computer Security

There are 3 project options available to 509 students this semester. Students in 409 must do Option 1.

Note: For students in 409 or 509, if you would like to do a different class project, feel free to come discuss your project ideas with me.

Project Option 1: Audit open source software

In this project, you will audit open-source software projects for security bugs. You can complete the project in three ways: finding bugs, writing patches, and writing exploits. The number of bugs you must find depends on the size of your team:

Team Size509 Total Points409 Total Points
15035
29060
312090

Each task earns points as follows (you can submit a patch and develop an exploit for the same bug, if you want):

TaskPoints
Find bug1
+ Confirm Bug1
+ Write patch1
+ Write exploit3

Each team member is required to demo one exploit to me at the end of the semester (you may work together to develop the exploits, but each member must demo a separate exploit). Note that simply causing the program to crash from malformed input (which is a denial-of-service attack), is not sufficient to count for your exploit demo, although I will give 1 point (instead of 3) for developing such an attack. You should send bug reports (and possibly patches) to the authors of the programs you audit. Your final report should include copies of all the bug reports you make and, whenever possible, a copy of the email from the authors acknowledging that you found a real, exploitable security bug.

Deadlines are:
DateTaskWeight of Grade
5/12Demo exploit20
5/14Final report80
You should email me to make a demo appointment on or before 5/12.

You can use Freshmeat and SourceForge to find projects to audit.

The following code auditing tools may be helpful

Project Option 2: Fine-grained capabilities for Linux

The Unix file-system interface is moving slowly towards a more capability-oriented model. In this project, we will help it along.

The first task is to enable users to grant capabilities to executable files, similar to the Unix setuid executable facility, but with finer-grained controls. You will need to write user-space programs to manage the capabilities granted to an executable, kernel support for implementing the capabilities, and an API with which the executable can use capabilities granted to it.

Capability representation

At a high-level, a capability will grant the application the ability to access some resource using the granter's authority. Thus, a capability must specify the authorithy and the resource. However, when the resource being accessed is a file, then accessing it may require traversing multiple directories in the file-system, and the granter may want the application to use different powers for each step. For example, the grantee may wish the application to use his user id for one step of the traversal, but one of his group ids for another step. Thus, a capability for accessing the filesystem should look like

(/p1/p2/p3/.../pn, c0, c1, c2, ..., cn, allowed-operations)
where credential c0 is used to access "/", and each other element pi is accessed using credential ci. Credentials are either user ids or group ids.

Your system should be extensible to support other types of resources, e.g. network sockets, shared memory, etc, although you do not have to implement these extensions. However, do include a "resource class" field in your capability data structures, so that the same data-structure can be extended later.

The allowed operations are resource-dependent. For files, they will be the standard read, write, and execute permissions. Note that a file capability may specify a file or a directory. For directories, the read, write, and execute bits will have their standard meanings.

Each credential will be a pair (user id, group id). The group id may be nil, in which case the user id will be used to access the corresponding resource. If the group id is not nil, then it will be used to access the corresponding resource. In this case, the user id is only present for auditing reasons, as explained below.

Capability management tools

Capabilities will be stored with executable files via extended attributes. See attr(5), getfattr(1), and setfattr(1) for information on extended attributes. Linux extended attributes are divided into several namespaces. You should store capabilities under the "security" namespace.

Each capability should have a name that the running process can use to refer to that capability. By default, the identifier for a file capability can just be the path to the file. However, the user should be able to over-ride this default.

You should provide a user-space program, cap, for managing the capabilities associated with files. Your cap program should be able to list the capabilities granted to an executable file, add capabilities to a file, and remove capabilites from a file:

  cap ls <executable>
  cap add [identifier] [-g gid|-u [uid]] <path> <allowed-operations> <executable>
  cap del <identifier> <executable>
The ls and del commands are self-explanatory. Anyone who can read the executable file may list the capabilities granted to that file. Anyone who can write to the file may add or delete capabilities. The add command enables the user to optionally specify an identifier for the capability to be added. If no identifier is given, then the path is used as the capability. The user may also indicate that the capability should use a given group id to access the given path. If the user running cap is not root, then they must be a member of the specified group. Root may also specify that the capability should use a specific user id by giving the -u option. Non-root users cannot specify an alternative user via -u. If neither -u or -g are given, then the capability should use the invoker's userid. The path must be absolute. If the path contains multiple elements, then the specified user id or group id applies to every element of the path. The user may create more complex capabilities that use different credentials for each path component by breaking the path into segments and specifying the credentials for each segment immediately before that segment. The allowed-operations must be a substring of "rwx".

Run-time implementation

When the executable runs, it needs some way to access the capabilities granted to it. You should add a new system call
  int capuse(const char *identifier, ...);
The extra optional arguments to this function are for future use. For file capabilities (the focus of this project), the program can simply call
  fd = capuse(identifier);
This will attempt to open the file (or directory) specified in the capability identified by identifier in the mode (read, write, and/or execute) specified by the allowed operations in the capability. The open will use the user or group ids specified in the capability for each step of the path resolution. Success will yield a file descriptor. Failure will result in -1. You will have to implement the capuse system call inside the Linux kernel. The kernel will need to scan the capabilities granted to the process to find the corresponding entry and then walk the path, using the specified user or group ids. Since capabilities are used much later than they are granted, we should take steps to ensure that the capability is being used as intended. Whenever the kernel traverses a path element using a user id, it should ensure that the containing directory is only writable by that user (or root), or that the containing directory has the sticky bit set and the current path element is owned by the user. Whenever the kernel traverses a path element using a group id, it should ensure that the containing directory is only writable by members of that group (or root). You may also extend file capabilities to distinguish directory capabilities from file capabilities, and have the kernel verify that the filename resolves to the correct object type at run time.

Optional directory extensions

When an executable obtains a directory file-handle via capuse, it can open files in that directory using the openat system call. However, it may also be able to open files outside that directory by using "..". Fix this by restricting the use of ".." relative to directories opened via capuse. The openat system call does not appear to treat its dirfd argument as a capability. In other words, if the calling process has a readable file-descriptor for the given directory but the process' credentials (i.e. effective user id, group id, etc,) do not have read-access to the directory, then openat may fail. Modify the openat system call (and other "at" system calls) to treat their dirfd argument as a capability. It may also be useful to have writable directory capabilities specify the user id and group id of files created in the directory using that capability.

Bugs in this design

There are certainly bugs in the design of this project. If you find one, please let me know.

Grading

Your grade will be determined primarily by a demo. You should schedule a demo with me before May 10th. You should send in your final code by May 14th.

Deadlines are:
DateTaskWeight of Grade
5/12Demo project70
5/14Code due30

Project Option 3: Develop a new bug-finding tool

In this project, you will develop a new static analysis tool to detect security bugs of your choice. Your tool may analyze C, C++, Java, PHP, Python, Perl, Ruby, or some other language. You should first pick a class of bugs, and then find (or create) a toolkit for parsing and analyzing the appropriate language. Example bug classes are There are also several toolkits for parsing and manipulating source code:

Before starting on this project, you should write a 1-2 page plan of attack and submit it to me for approval. Your plan should identify the class of bugs you hope to detect (including a few examples), give some recent bug reports demonstrating that this is an important security bug, describe a high-level algorithm for detecting them, and list several open source projects you can use to test your algorithm.

After developing your bug-finding tool, you should test it on several open-source projects. You should plan a demo of your project with me sometime before the end of the semester, and you must turn in a 6-8 page final report describing your algorithm and experimental results at the end of the semester. You may work in teams of 2-3 students.

Deadlines are:
DateTaskWeight of Grade
4/131-2 page proposal10
5/12Demo40
5/14Final report50
You should email me to make a demo appointment on or before 5/12.

You can use Freshmeat and SourceForge to find projects to audit.