CVE-2023-0614 s4-dsdb: Treat confidential attributes as unindexed
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Thu, 23 Feb 2023 21:03:25 +0000 (10:03 +1300)
committerJule Anger <janger@samba.org>
Mon, 20 Mar 2023 09:03:38 +0000 (10:03 +0100)
In the unlikely case that someone adds a confidential indexed attribute
to the schema, LDAP search expressions on that attribute could disclose
information via timing differences. Let's not use the index for searches
on confidential attributes.

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

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dsdb/samdb/ldb_modules/extended_dn_in.c
source4/dsdb/schema/schema_description.c
source4/dsdb/schema/schema_init.c
source4/dsdb/schema/schema_set.c

index 1dc1e1f2d4294c171a9dc2f1dab6ea240ad96037..248bb66f0399e9b0ed2daaba9c8e00a16d1da000 100644 (file)
@@ -423,7 +423,15 @@ static int extended_dn_filter_callback(struct ldb_parse_tree *tree, void *privat
        guid_val = ldb_dn_get_extended_component(dn, "GUID");
        sid_val  = ldb_dn_get_extended_component(dn, "SID");
 
-       if (!guid_val && !sid_val && (attribute->searchFlags & SEARCH_FLAG_ATTINDEX)) {
+       /*
+        * Is the attribute indexed? By treating confidential attributes
+        * as unindexed, we force searches to go through the unindexed
+        * search path, avoiding observable timing differences.
+        */
+       if (!guid_val && !sid_val &&
+           (attribute->searchFlags & SEARCH_FLAG_ATTINDEX) &&
+           !(attribute->searchFlags & SEARCH_FLAG_CONFIDENTIAL))
+       {
                /* if it is indexed, then fixing the string DN will do
                   no good here, as we will not find the attribute in
                   the index. So for now fall through to a standard DN
index 243a02a15f31743964fc7dd27f79fbae6fe04d82..5fc70154bf86cafe5a168a4f645f524db2541dc2 100644 (file)
@@ -160,6 +160,13 @@ char *schema_attribute_to_extendedInfo(TALLOC_CTX *mem_ctx, const struct dsdb_at
                                               attribute->rangeUpper,
                                               GUID_hexstring(tmp_ctx, &attribute->schemaIDGUID),
                                               GUID_hexstring(tmp_ctx, &attribute->attributeSecurityGUID),
+                                              /*
+                                               * We actually ignore the indexed
+                                               * flag for confidential
+                                               * attributes, but we'll include
+                                               * it for the purposes of
+                                               * description.
+                                               */
                                               (attribute->searchFlags & SEARCH_FLAG_ATTINDEX),
                                               attribute->systemOnly);
        talloc_free(tmp_ctx);
index a3b00497b6bdb99c5b3d530f7bde189a223669d2..c8197b86306144bb47af4d260f8266b95eea1a50 100644 (file)
@@ -514,8 +514,15 @@ static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
        if (attr->isSingleValued) {
                a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
        }
-       
-       if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+
+       /*
+        * Is the attribute indexed? By treating confidential attributes as
+        * unindexed, we force searches to go through the unindexed search path,
+        * avoiding observable timing differences.
+        */
+       if (attr->searchFlags & SEARCH_FLAG_ATTINDEX &&
+           !(attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL))
+       {
                a->flags |= LDB_ATTR_FLAG_INDEXED;
        }
 
index 45faa0912ec648c59b8b93b3909c87c00e18c6ae..03cf240559524a4b20a5cc4f09a6e9b3df4ef634 100644 (file)
@@ -221,7 +221,14 @@ int dsdb_schema_set_indices_and_attributes(struct ldb_context *ldb,
                        break;
                }
 
-               if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+               /*
+                * Is the attribute indexed? By treating confidential attributes
+                * as unindexed, we force searches to go through the unindexed
+                * search path, avoiding observable timing differences.
+                */
+               if (attr->searchFlags & SEARCH_FLAG_ATTINDEX &&
+                   !(attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL))
+               {
                        /*
                         * When preparing to downgrade Samba, we need to write
                         * out an LDB without the new key word ORDERED_INTEGER.