CVE-2020-15862: Improper Privilege Management (CWE-269)
value: Net-SNMP through 5.8 has Improper Privilege Management because SNMP WRITE access to the EXTEND MIB provides the ability to run arbitrary commands as root.
CWE description: The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
CVSS v3 base score: 7.8
Published: 2020-08-20T01:17Z
Repository: https://github.com/net-snmp/net-snmp
Language: C
Files changed: agent/mibgroup/agent/extend.c
Commit date: 2020-07-23 16:17:27 -0700
Commit message: make the extend mib read-only by default

Diff: diff --git a/agent/mibgroup/agent/extend.c b/agent/mibgroup/agent/extend.c
index 379ea603bc..bd8143057f 100644
--- a/agent/mibgroup/agent/extend.c
+++ b/agent/mibgroup/agent/extend.c
@@ -14,10 +14,16 @@
 #include "util_funcs/header_simple_table.h"
 #include "mibdefs.h"
 #define SHELLCOMMAND 3
 #endif
 
+/*  This mib is potentially dangerous to turn on by default, since it
+ *  allows arbitrary commands to be set by anyone with SNMP WRITE
+ *  access to the MIB table.  If all of your users are "root" level
+ *  users, then it may be safe to turn on. */
+#define ENABLE_EXTEND_WRITE_ACCESS 0
+
 netsnmp_feature_require(extract_table_row_data);
 netsnmp_feature_require(table_data_delete_table);
 #ifndef NETSNMP_NO_WRITE_SUPPORT
 netsnmp_feature_require(insert_table_row);
 #endif /* NETSNMP_NO_WRITE_SUPPORT */
@@ -740,11 +746,11 @@ handle_nsExtendConfigTable(netsnmp_mib_handler          *handler,
          *     and the cache timeout adjusted, but these changes are
          *     not persistent.
          *
          **********/
 
-#ifndef NETSNMP_NO_WRITE_SUPPORT
+#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
         case MODE_SET_RESERVE1:
             /*
              * Validate the new assignments
              */
             switch (table_info->colnum) {
@@ -1066,19 +1072,19 @@ handle_nsExtendConfigTable(netsnmp_mib_handler          *handler,
                     _free_extension( extension, eptr );
                     break;
                 }
             }
             break;
-#endif /* !NETSNMP_NO_WRITE_SUPPORT */ 
+#endif /* !NETSNMP_NO_WRITE_SUPPORT and ENABLE_EXTEND_WRITE_ACCESS */
 
         default:
             netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR);
             return SNMP_ERR_GENERR;
         }
     }
 
-#ifndef NETSNMP_NO_WRITE_SUPPORT
+#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
     /*
      * If we're marking a given row as active,
      *  then we need to check that it's ready.
      */
     if (need_to_validate) {
@@ -1099,11 +1105,11 @@ handle_nsExtendConfigTable(netsnmp_mib_handler          *handler,
                     return SNMP_ERR_INCONSISTENTVALUE;
                 }
             }
         }
     }
-#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+#endif /* !NETSNMP_NO_WRITE_SUPPORT && ENABLE_EXTEND_WRITE_ACCESS */
     
     return SNMP_ERR_NOERROR;
 }
 
 
@@ -1585,11 +1591,11 @@ fixExec2Error(int action,
     unsigned int idx;
 
     idx = name[name_len-1] -1;
     exten = &compatability_entries[ idx ];
 
-#ifndef NETSNMP_NO_WRITE_SUPPORT
+#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
     switch (action) {
     case MODE_SET_RESERVE1:
         if (var_val_type != ASN_INTEGER) {
             snmp_log(LOG_ERR, "Wrong type != int\n");
             return SNMP_ERR_WRONGTYPE;
@@ -1606,9 +1612,9 @@ fixExec2Error(int action,
         return SNMP_ERR_NOERROR;
 
     case MODE_SET_COMMIT:
         netsnmp_cache_check_and_reload( exten->efix_entry->cache );
     }
-#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+#endif /* !NETSNMP_NO_WRITE_SUPPORT && ENABLE_EXTEND_WRITE_ACCESS */
     return SNMP_ERR_NOERROR;
 }
 #endif /* USING_UCD_SNMP_EXTENSIBLE_MODULE */

Vulnerable code: #ifndef NETSNMP_NO_WRITE_SUPPORT
#endif /* !NETSNMP_NO_WRITE_SUPPORT */ 
#ifndef NETSNMP_NO_WRITE_SUPPORT
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
#ifndef NETSNMP_NO_WRITE_SUPPORT
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
Fixed code: /*  This mib is potentially dangerous to turn on by default, since it
 *  allows arbitrary commands to be set by anyone with SNMP WRITE
 *  access to the MIB table.  If all of your users are "root" level
 *  users, then it may be safe to turn on. */
#define ENABLE_EXTEND_WRITE_ACCESS 0

#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
#endif /* !NETSNMP_NO_WRITE_SUPPORT and ENABLE_EXTEND_WRITE_ACCESS */
#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
#endif /* !NETSNMP_NO_WRITE_SUPPORT && ENABLE_EXTEND_WRITE_ACCESS */
#if !defined(NETSNMP_NO_WRITE_SUPPORT) && ENABLE_EXTEND_WRITE_ACCESS
#endif /* !NETSNMP_NO_WRITE_SUPPORT && ENABLE_EXTEND_WRITE_ACCESS */