$ 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/~cse331/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 pwn your computerHere, the "..." may be additional output caused as a side-effect of your attack.
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.
/*
* 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: 06 September 2006