CVE-2019-19905 (published 2019-12-19T18:15Z)

NetHack 3.6.x before 3.6.4 is prone to a buffer overflow vulnerability when reading very long lines from configuration files. This affects systems that have NetHack installed suid/sgid, and shared systems that allow users to upload their own configuration files.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-120
cwe_name: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
extended_description: A buffer overflow condition exists when a product attempts to put more data in a buffer than it can hold, or when it attempts to put data in a memory area outside of the boundaries of a buffer. The simplest type of error, and the most common cause of buffer overflows, is the "classic" case in which the product copies the buffer without restricting how much is copied. Other variants exist, but the existence of a classic overflow strongly suggests that the programmer is not considering even the most basic of security protections.
         

Fix information:
repo_url: https://github.com/NetHack/NetHack
commit_details: repo_url: https://github.com/NetHack/NetHack
author: PatR
author_date: 2019-12-17 15:41:58-08:00
msg: parse_conf_file fix fix
repository: repo_url: https://github.com/NetHack/NetHack
repo_name: NetHack/NetHack
description: Official NetHack Git Repository
repo_language: C
owner: NetHack
file_changes: filename: files.c
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-/* NetHack 3.6	files.c	$NHDT-Date: 1574116097 2019/11/18 22:28:17 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.272 $ */
+/* NetHack 3.6	files.c	$NHDT-Date: 1576626110 2019/12/17 23:41:50 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.276 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -3160,7 +3160,8 @@ boolean FDECL((*proc), (char *));
                         free(buf);
                     }
                     buf = strcat(tmpbuf, ep);
-                    buf[sizeof inbuf - 1] = '\0';
+                    if (strlen(buf) >= sizeof inbuf)
+                        buf[sizeof inbuf - 1] = '\0';
                 }
 
                 if (morelines || (ignoreline && !oldline))

programming_language: C
repo_url: https://github.com/NetHack/NetHack
commit_details: repo_url: https://github.com/NetHack/NetHack
author: PatR
author_date: 2019-12-13 13:36:38-08:00
msg: fix potential buffer overflow loading config file
repository: repo_url: https://github.com/NetHack/NetHack
repo_name: NetHack/NetHack
description: Official NetHack Git Repository
repo_language: C
owner: NetHack
file_changes: filename: fixes36.4
change_type: ModificationType.MODIFY
diff: @@ -1,8 +1,8 @@
 $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1576287569 2019/12/14 01:39:29 $
 
-This fixes36.4 file is here to capture information about updates in the 3.6.x
-lineage following the release of 3.6.3 in December 2019.  Hypothetical version
-3.6.4 may not be released, in which case these fixes will appear in 3.7.0.
+fixes36.4 contains a terse summary of changes made to 3.6.3 in order to
+produce 3.6.4.
+ 
 
 General Fixes and Modified Features
 -----------------------------------
@@ -15,11 +15,7 @@ message "your knapsack can't accomodate any more items" when picking stuff up
 	or removing such from container was inaccurate if there was some gold
 	pending; vary the message rather than add more convoluted pickup code
 dozen-ish assorted spelling/typo fixes in messages and source comments
-flying hero could not use a hole deliberately with '>'
-
-
-Fixes to Post-3.6.3 Problems that Were Exposed Via git Repository
-------------------------------------------------------------------
+fix potential buffer overflow when parsing run-time configuration file
 
 
 Platform- and/or Interface-Specific Fixes or Features
@@ -30,13 +26,6 @@ allow run-from-removable-device on Windows
 
 General New Features
 --------------------
-
-
-NetHack Community Patches (or Variation) Included
--------------------------------------------------
-
-
-Code Cleanup and Reorganization
--------------------------------
+none
 
 

programming_language: Markdown
filename: files.c
change_type: ModificationType.MODIFY
diff: @@ -2309,10 +2309,14 @@ char *origbuf;
     int len;
     boolean retval = TRUE;
 
+    while (*origbuf == ' ' || *origbuf == '\t') /* skip leading whitespace */
+        ++origbuf;                   /* (caller probably already did this) */
+    (void) strncpy(buf, origbuf, sizeof buf - 1);
+    buf[sizeof buf - 1] = '\0'; /* strncpy not guaranteed to NUL terminate */
     /* convert any tab to space, condense consecutive spaces into one,
        remove leading and trailing spaces (exception: if there is nothing
        but spaces, one of them will be kept even though it leads/trails) */
-    mungspaces(strcpy(buf, origbuf));
+    mungspaces(buf);
 
     /* find the '=' or ':' */
     bufp = find_optparam(buf);
@@ -3034,7 +3038,11 @@ boolean
 proc_wizkit_line(buf)
 char *buf;
 {
-    struct obj *otmp = readobjnam(buf, (struct obj *) 0);
+    struct obj *otmp;
+
+    if (strlen(buf) >= BUFSZ)
+        buf[BUFSZ - 1] = '\0';
+    otmp = readobjnam(buf, (struct obj *) 0);
 
     if (otmp) {
         if (otmp != &zeroobj)
@@ -3142,22 +3150,23 @@ boolean FDECL((*proc), (char *));
 
                 /* merge now read line with previous ones, if necessary */
                 if (!ignoreline) {
-                    len = (int) strlen(inbuf) + 1;
+                    len = (int) strlen(ep) + 1; /* +1: final '\0' */
                     if (buf)
-                        len += (int) strlen(buf);
+                        len += (int) strlen(buf) + 1; /* +1: space */
                     tmpbuf = (char *) alloc(len);
+                    *tmpbuf = '\0';
                     if (buf) {
-                        Sprintf(tmpbuf, "%s %s", buf, inbuf);
+                        Strcat(strcpy(tmpbuf, buf), " ");
                         free(buf);
-                    } else
-                        Strcpy(tmpbuf, inbuf);
-                    buf = tmpbuf;
+                    }
+                    buf = strcat(tmpbuf, ep);
+                    buf[sizeof inbuf - 1] = '\0';
                 }
 
                 if (morelines || (ignoreline && !oldline))
                     continue;
 
-                if (handle_config_section(ep)) {
+                if (handle_config_section(buf)) {
                     free(buf);
                     buf = (char *) 0;
                     continue;
@@ -3179,11 +3188,11 @@ boolean FDECL((*proc), (char *));
                     }
                     bufp++;
                     if (config_section_chosen)
-                        free(config_section_chosen);
+                        free(config_section_chosen), config_section_chosen = 0;
                     section = choose_random_part(bufp, ',');
-                    if (section)
+                    if (section) {
                         config_section_chosen = dupstr(section);
-                    else {
+                    } else {
                         config_error_add("No config section to choose");
                         rv = FALSE;
                     }
@@ -3300,6 +3309,8 @@ int which_set;
     struct symparse *symp;
     char *bufp, *commentp, *altp;
 
+    if (strlen(buf) >= BUFSZ)
+        buf[BUFSZ - 1] = '\0';
     /* convert each instance of whitespace (tabs, consecutive spaces)
        into a single space; leading and trailing spaces are stripped */
     mungspaces(buf);

programming_language: C