CVE-2018-10918: cracknames: Fix DoS (NULL pointer de-ref) when not servicePrincipalNa...
authorAndrew Bartlett <abartlet@samba.org>
Mon, 30 Jul 2018 02:00:18 +0000 (14:00 +1200)
committerKarolin Seeger <kseeger@samba.org>
Sat, 11 Aug 2018 06:16:01 +0000 (08:16 +0200)
This regression was introduced in Samba 4.7 by bug 12842 and in
master git commit eb2e77970e41c1cb62c041877565e939c78ff52d.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13552

CVE-2018-10918: Denial of Service Attack on AD DC DRSUAPI server.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
source4/dsdb/samdb/cracknames.c
source4/torture/drs/python/cracknames.py

index d43f510b949e3e61803f833b8d0fdae9e5b2584c..3b215ac0ec96efca6a6f7ceecc52417b36db0d41 100644 (file)
@@ -1253,7 +1253,13 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                return WERR_OK;
        }
        case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
-               if (result->elements[0].num_values > 1) {
+               struct ldb_message_element *el
+                       = ldb_msg_find_element(result,
+                                              "servicePrincipalName");
+               if (el == NULL) {
+                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+                       return WERR_OK;
+               } else if (el->num_values > 1) {
                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
                        return WERR_OK;
                }
index d8c8ae53d60904b060722162c6f11a6151c5f710..9bf90f9c9973d67ef9ceee3bcf8b22e2724a8d62 100644 (file)
@@ -149,6 +149,44 @@ class DrsCracknamesTestCase(drs_base.DrsBaseTestCase):
 
         self.ldb_dc1.delete(user)
 
+    def test_NoSPNAttribute(self):
+        """
+        Verifies that, if we try and cracknames with the desired output
+        being an SPN, it returns
+        DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE.
+        """
+        username = "Cracknames_no_SPN"
+        user = "cn=%s,%s" % (username, self.ou)
+
+        user_record = {
+            "dn": user,
+            "objectclass": "user",
+            "sAMAccountName" : username,
+            "userPrincipalName" : "test4@test.com",
+            "displayName" : "test4"}
+
+        self.ldb_dc1.add(user_record)
+
+        (result, ctr) = self._do_cracknames(user,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID)
+
+        self.assertEquals(ctr.count, 1)
+        self.assertEquals(ctr.array[0].status,
+                          drsuapi.DRSUAPI_DS_NAME_STATUS_OK)
+
+        user_guid = ctr.array[0].result_name
+
+        (result, ctr) = self._do_cracknames(user_guid,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_GUID,
+                                            drsuapi.DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL)
+
+        self.assertEquals(ctr.count, 1)
+        self.assertEquals(ctr.array[0].status,
+                          drsuapi.DRSUAPI_DS_NAME_STATUS_NOT_FOUND)
+
+        self.ldb_dc1.delete(user)
+
     def _do_cracknames(self, name, format_offered, format_desired):
         req = drsuapi.DsNameRequest1()
         names = drsuapi.DsNameString()