xorl %eax, %eax

NetBSD-SA2009-007: Multiple Buffer overflows in hack(6)

leave a comment »

This kind of irony considering the application’s name. Anyway, hack(6) is a game which is installed as a setgid binary. So, there is not much you can do with it apart from having fun exploiting “hack”. According to the official advisory, the bug was discovered and fixed by David A. Holland. Here is the first buggy routine which can be found at src/games/hack/hack.main.c.

int
main(int argc, char *argv[])
{
	int             fd;
#ifdef CHDIR
	char           *dir;
#endif

	/* Check for dirty tricks with closed fds 0, 1, 2 */
	fd = open("/dev/null", O_RDONLY);
	if (fd < 3)
		exit(1);
	close(fd);

	hname = argv&#91;0&#93;;
	hackpid = getpid();
 ...
#ifdef WIZARD
 ...
		if ((sfoo = getenv("GENOCIDED")) != NULL) {
			if (*sfoo == '!') {
				const struct permonst *pm = mons;
				char           *gp = genocided;

				while (pm < mons + CMNUM + 2) {
					if (!strchr(sfoo, pm->mlet))
						*gp++ = pm->mlet;
					pm++;
				}
				*gp = 0;
			} else
				(void) strcpy(genocided, sfoo);
			(void) strcpy(fut_geno, genocided);
		}
      ...
}

Where fut_geno as we can see in hack.h is a 60 bytes long character array. This extremely simple strcpy overflow which can be triggered just by doing export GENOCIDED=`perl -e ‘print “X” x 120’` or something. Of course, you cannot have ‘!’ character as the first character of your string but who cares?
The fix to this bug was to replace the vulnerable strcpy routine with strlcpy like that…

 			} else
-				(void) strcpy(genocided, sfoo);
+				(void) strlcpy(genocided, sfoo,
+						sizeof(genocided));
 			(void) strcpy(fut_geno, genocided);

The second one can be found in hack.unix.c and it is the following function.

void
gethdate(char *name)
{

#define MAXPATHLEN 1024

const char *np, *path;
char filename[MAXPATHLEN + 1];
if (strchr(name, ‘/’) != NULL || (path = getenv(“PATH”)) == NULL)
path = “”;

for (;;) {
if ((np = strchr(path, ‘:’)) == NULL)
np = path + strlen(path); /* point to end str */
if (np – path <= 1) /* %% */ (void) strcpy(filename, name); else { (void) strncpy(filename, path, np - path); filename[np - path] = '/'; (void) strcpy(filename + (np - path) + 1, name); } if (stat(filename, &hbuf) == 0) return; ... #endif } [/sourcecode] Well, again two straightforward stack overflows which were fixed with the following patch. [sourcecode language="c"] if (np - path <= 1) /* %% */ - (void) strcpy(filename, name); + (void) strlcpy(filename, name, sizeof(filename)); else { - (void) strncpy(filename, path, np - path); - filename[np - path] = '/'; - (void) strcpy(filename + (np - path) + 1, name); + (void) snprintf(filename, sizeof(filename), + "%.*s/%s", + (int)(np - path), path, name); } [/sourcecode] The advisory mentions that there are numerous more memory corruption vulnerabilities in games/hack but are uninmportant in comparison to the above two from a security prospective.

Written by xorl

July 8, 2009 at 00:20

Posted in bugs, netbsd

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s