Project 1 : Buffer Overflows
CIS/TCOM 551


Due: January 31, 2006

Description

The blame service is a simple system for assigning blame, written by our hero, Feckless C. Coder, PhD. The program accepts on standard input the name of a scapegoat and prints on standard output a message asserting that person's universal culpability. For example:
        $ echo "Steve Zdancewic" | ./blame
        It's all Steve Zdancewic's fault.
or, if you prefer:
        $ echo "Bill Gates" | ./blame
        It's all Bill Gates's fault.
The program is designed to operate as a network service, e.g., from the "inetd" daemon under Unix.

Source code for blame.c is attached below and is also available at http://www.cis.upenn.edu/~cis551/blame.c.

Simple-minded string processing aside (it would be more correct, after all, to say that "It's all Bill Gates' fault"), there is a serious problem with the blame program. Despite Feckless' best efforts, a bug allows anyone who can provide input to this program to run arbitrary code on the target machine. (What might happen if it is run as a network service under inetd, as suggested in the comments?)

Your job is to create input that will cause the blame service to print out the helpful message "Now I pwn your computer" before it terminates. For example:

	$ cat exploit_file | ./blame
	...
	Now I own your computer

Here, the "..." may be additional output caused as a side-effect of your attack.

Deliverables

  1. Write a well documented program that generates exploit_file. (You can assume you'd have access to the object code for the instance of blame against which it will be run). Your program should work on the Linux platform available on the eniac-l.seas.upenn.edu machine pool. The gcc compiler and gdb debugger are already installed. If, for some reason, you do not have an account on eniac-l.seas.upenn.edu contact one of the course staff members.

    Submit the program that generates your exploit_file as well as any tools you use to generate parameters and constants. Your software should be sufficiently documented to allow a novice programmer to port your code to other platforms or to modify it to exploit similar weaknesses in other programs. In other words, your submission should be suitable as a tutorial on exploiting (and avoiding) this class of vulnerability.

  2. Fix the blame.c implementation so that it is not vulnerable to this buffer overflow attack, but still has the same behavior as the original program for inputs that fit into the buffer INPUT_BUFFER. How do you know your program is secure?

  3. Your submission should consist of a single .tar, .tar.gz or .tgz file. Send it by e-mail to Karl Mazurak (mazurak AT cis.upenn.edu), the class TA. The archive should include a README file containing your full name, e-mail address, and a list of the contents of the directory you submit. For help with creating a tar file, read the tar man pages.

Resources

You may find these links useful in your task. Feel free to use additional sources for learning about C, gdb, gcc, but do not submit code that you did not create entirely by yourself. Please see the course policies for acceptable use of external resources.

Blame server source code (blame.c)

/*
 * Blame server.  Assigns blame to the person of your choice.
 *
 * Usage: blame
 *	(reads one line from standard input)
 *
 * To compile:
 *	cc blame.c -o blame
 *
 * Install under inetd as follows:
 *  blame	stream	tcp	nowait	root	/path/to/blame	blame
 *
 * Copyright 2004 by Feckless C. Coder, PhD.
 */

#include <stdio.h>
#include <string.h>
#define INPUT_BUFFER 256  /* maximum name size */

/*
 * read input, copy into s 
 * gets() is insecure and prints a warning
 *    so we use this instead
 */
void getline(char *s)
{
	int c;
	
	while ((c=getchar()) != EOF)
		*s++ = c;
	*s = '\0';
}

/*
 * convert newlines to nulls in place
 */
void purgenewlines(char *s)
{
	int l;

	l = strlen(s);

	while (l--)
		if (s[l] == '\n')
			s[l] = '\0';
}


int main()
{
	char scapegoat[INPUT_BUFFER];

	getline(scapegoat);
	/* this check ensures there's no buffer overflow */
	if (strlen(scapegoat) < INPUT_BUFFER) {
		purgenewlines(scapegoat);
		printf("It's all %s's fault.\n", scapegoat);
	}
	return 0;
}


Last Revised: 23 January 2006