Your message dated Mon, 05 Feb 2018 15:21:00 +0000
with message-id <e1eiizo-0005e4...@fasolo.debian.org>
and subject line Bug#888451: fixed in 389-ds-base 1.3.7.9-1
has caused the Debian Bug report #888451,
regarding 389-ds-base: CVE-2017-15135: Authentication bypass due to lack of 
size check in slapi_ct_memcmp function in ch_malloc.c
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
888451: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=888451
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Source: 389-ds-base
Version: 1.3.7.8-4
Severity: grave
Tags: patch security upstream

Hi,

the following vulnerability was published for 389-ds-base.

CVE-2017-15135[0]:
| It was found that 389-ds-base since 1.3.6.1 up to and including
| 1.4.0.3 did not always handle internal hash comparison operations
| correctly during the authentication process. A remote, unauthenticated
| attacker could potentially use this flaw to bypass the authentication
| process under very rare and specific circumstances.

If you fix the vulnerability please also make sure to include the
CVE (Common Vulnerabilities & Exposures) id in your changelog entry.

For further information see:

[0] https://security-tracker.debian.org/tracker/CVE-2017-15135
    https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15135
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1525628

Please adjust the affected versions in the BTS as needed, the issue
was introduced after the CVE-2016-5405 fix it is said, needs to be
verfied which suites are affected, at least stretch seems so. So far I
only looked at sid source.

Regards,
Salvatore
>From 872c98cd1b5059a4b76e3707d92f1445663db83d Mon Sep 17 00:00:00 2001
From: William Brown <firsty...@redhat.com>
Date: Thu, 18 Jan 2018 11:27:58 +1000
Subject: [PATCH] Ticket bz1525628 - invalid password migration causes unauth
 bind

Bug Description:  Slapi_ct_memcmp expects both inputs to be
at LEAST size n. If they are not, we only compared UP to n.

Invalid migrations of passwords (IE {CRYPT}XX) would create
a pw which is just salt and no hash. ct_memcmp would then
only verify the salt bits and would allow the authentication.

This relies on an administrative mistake both of allowing
password migration (nsslapd-allow-hashed-passwords) and then
subsequently migrating an INVALID password to the server.

Fix Description:  slapi_ct_memcmp now access n1, n2 size
and will FAIL if they are not the same, but will still compare
n bytes, where n is the "longest" memory, to the first byte
of the other to prevent length disclosure of the shorter
value (generally the mis-migrated password)

https://bugzilla.redhat.com/show_bug.cgi?id=1525628

Author: wibrown

Review by: ???
---
 .../bz1525628_ct_memcmp_invalid_hash_test.py       | 56 ++++++++++++++++++++++
 ldap/servers/plugins/pwdstorage/clear_pwd.c        |  4 +-
 ldap/servers/plugins/pwdstorage/crypt_pwd.c        |  4 +-
 ldap/servers/plugins/pwdstorage/md5_pwd.c          |  4 +-
 ldap/servers/plugins/pwdstorage/sha_pwd.c          |  4 +-
 ldap/servers/plugins/pwdstorage/smd5_pwd.c         |  2 +-
 ldap/servers/slapd/ch_malloc.c                     | 36 ++++++++++++--
 ldap/servers/slapd/slapi-plugin.h                  |  2 +-
 8 files changed, 97 insertions(+), 15 deletions(-)
 create mode 100644 
dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py

diff --git 
a/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py 
b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
new file mode 100644
index 0000000..2f38384
--- /dev/null
+++ b/dirsrvtests/tests/suites/password/bz1525628_ct_memcmp_invalid_hash_test.py
@@ -0,0 +1,56 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2018 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+
+import ldap
+import pytest
+import logging
+from lib389.topologies import topology_st
+from lib389._constants import PASSWORD, DEFAULT_SUFFIX
+
+from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+def test_invalid_hash_fails(topology_st):
+    """When given a malformed hash from userpassword migration
+    slapi_ct_memcmp would check only to the length of the shorter
+    field. This affects some values where it would ONLY verify
+    the salt is valid, and thus would allow any password to bind.
+
+    :id: 8131c029-7147-47db-8d03-ec5db2a01cfb
+    :setup: Standalone Instance
+    :steps:
+        1. Create a user
+        2. Add an invalid password hash (truncated)
+        3. Attempt to bind
+    :expectedresults:
+        1. User is added
+        2. Invalid pw hash is added
+        3. Bind fails
+    """
+    log.info("Running invalid hash test")
+
+    # Allow setting raw password hashes for migration.
+    topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
+
+    users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
+    user = users.create(properties=TEST_USER_PROPERTIES)
+    user.set('userPassword', '{CRYPT}XX')
+
+    # Attempt to bind. This should fail.
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
+        user.bind(PASSWORD)
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
+        user.bind('XX')
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
+        user.bind('{CRYPT}XX')
+
+    log.info("PASSED")
+
diff --git a/ldap/servers/plugins/pwdstorage/clear_pwd.c 
b/ldap/servers/plugins/pwdstorage/clear_pwd.c
index f5e6f9d..3d34075 100644
--- a/ldap/servers/plugins/pwdstorage/clear_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/clear_pwd.c
@@ -39,7 +39,7 @@ clear_pw_cmp(const char *userpwd, const char *dbpwd)
          * However, even if the first part of userpw matches dbpwd, but len 
!=, we
          * have already failed anyawy. This prevents substring matching.
          */
-        if (slapi_ct_memcmp(userpwd, dbpwd, len_dbp) != 0) {
+        if (slapi_ct_memcmp(userpwd, dbpwd, len_user, len_dbp) != 0) {
             result = 1;
         }
     } else {
@@ -51,7 +51,7 @@ clear_pw_cmp(const char *userpwd, const char *dbpwd)
          * dbpwd to itself. We have already got result == 1 if we are here, so 
we are
          * just trying to take up time!
          */
-        if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp)) {
+        if (slapi_ct_memcmp(dbpwd, dbpwd, len_dbp, len_dbp)) {
             /* Do nothing, we have the if to fix a coverity check. */
         }
     }
diff --git a/ldap/servers/plugins/pwdstorage/crypt_pwd.c 
b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
index 3bd2265..0dccd1b 100644
--- a/ldap/servers/plugins/pwdstorage/crypt_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/crypt_pwd.c
@@ -65,13 +65,13 @@ crypt_close(Slapi_PBlock *pb __attribute__((unused)))
 int
 crypt_pw_cmp(const char *userpwd, const char *dbpwd)
 {
-    int rc;
+    int32_t rc;
     char *cp;
     PR_Lock(cryptlock);
     /* we use salt (first 2 chars) of encoded password in call to crypt() */
     cp = crypt(userpwd, dbpwd);
     if (cp) {
-        rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd));
+        rc = slapi_ct_memcmp(dbpwd, cp, strlen(dbpwd), strlen(cp));
     } else {
         rc = -1;
     }
diff --git a/ldap/servers/plugins/pwdstorage/md5_pwd.c 
b/ldap/servers/plugins/pwdstorage/md5_pwd.c
index 1e2cf58..2c2aaca 100644
--- a/ldap/servers/plugins/pwdstorage/md5_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/md5_pwd.c
@@ -30,7 +30,7 @@
 int
 md5_pw_cmp(const char *userpwd, const char *dbpwd)
 {
-    int rc = -1;
+    int32_t rc = -1;
     char *bver;
     PK11Context *ctx = NULL;
     unsigned int outLen;
@@ -57,7 +57,7 @@ md5_pw_cmp(const char *userpwd, const char *dbpwd)
     bver = NSSBase64_EncodeItem(NULL, (char *)b2a_out, sizeof b2a_out, 
&binary_item);
     /* bver points to b2a_out upon success */
     if (bver) {
-        rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd));
+        rc = slapi_ct_memcmp(bver, dbpwd, strlen(dbpwd), strlen(bver));
     } else {
         slapi_log_err(SLAPI_LOG_PLUGIN, MD5_SUBSYSTEM_NAME,
                       "Could not base64 encode hashed value for password 
compare");
diff --git a/ldap/servers/plugins/pwdstorage/sha_pwd.c 
b/ldap/servers/plugins/pwdstorage/sha_pwd.c
index 1fbe0bc..8af3611 100644
--- a/ldap/servers/plugins/pwdstorage/sha_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/sha_pwd.c
@@ -122,9 +122,9 @@ sha_pw_cmp(const char *userpwd, const char *dbpwd, unsigned 
int shaLen)
 
     /* the proof is in the comparison... */
     if (hash_len >= shaLen) {
-        result = slapi_ct_memcmp(userhash, dbhash, shaLen);
+        result = slapi_ct_memcmp(userhash, dbhash, shaLen, shaLen);
     } else {
-        result = slapi_ct_memcmp(userhash, dbhash + OLD_SALT_LENGTH, hash_len 
- OLD_SALT_LENGTH);
+        result = slapi_ct_memcmp(userhash, dbhash + OLD_SALT_LENGTH, hash_len 
- OLD_SALT_LENGTH, hash_len - OLD_SALT_LENGTH);
     }
 
 loser:
diff --git a/ldap/servers/plugins/pwdstorage/smd5_pwd.c 
b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
index a83ac6f..cbfc74f 100644
--- a/ldap/servers/plugins/pwdstorage/smd5_pwd.c
+++ b/ldap/servers/plugins/pwdstorage/smd5_pwd.c
@@ -82,7 +82,7 @@ smd5_pw_cmp(const char *userpwd, const char *dbpwd)
     PK11_DestroyContext(ctx, 1);
 
     /* Compare everything up to the salt. */
-    rc = slapi_ct_memcmp(userhash, dbhash, MD5_LENGTH);
+    rc = slapi_ct_memcmp(userhash, dbhash, MD5_LENGTH, MD5_LENGTH);
 
 loser:
     if (dbhash && dbhash != quick_dbhash)
diff --git a/ldap/servers/slapd/ch_malloc.c b/ldap/servers/slapd/ch_malloc.c
index ef436b3..90a2b2c 100644
--- a/ldap/servers/slapd/ch_malloc.c
+++ b/ldap/servers/slapd/ch_malloc.c
@@ -336,8 +336,8 @@ slapi_ch_smprintf(const char *fmt, ...)
 
 /* Constant time memcmp. Does not shortcircuit on failure! */
 /* This relies on p1 and p2 both being size at least n! */
-int
-slapi_ct_memcmp(const void *p1, const void *p2, size_t n)
+int32_t
+slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2)
 {
     int result = 0;
     const unsigned char *_p1 = (const unsigned char *)p1;
@@ -347,9 +347,35 @@ slapi_ct_memcmp(const void *p1, const void *p2, size_t n)
         return 2;
     }
 
-    for (size_t i = 0; i < n; i++) {
-        if (_p1[i] ^ _p2[i]) {
-            result = 1;
+    if (n1 == n2) {
+        for (size_t i = 0; i < n1; i++) {
+            if (_p1[i] ^ _p2[i]) {
+                result = 1;
+            }
+        }
+    } else {
+        const unsigned char *_pa;
+        const unsigned char *_pb;
+        size_t nl;
+        if (n2 > n1) {
+            _pa = _p2;
+            _pb = _p2;
+            nl = n2;
+        } else {
+            _pa = _p1;
+            _pb = _p1;
+            nl = n1;
+        }
+        /* We already fail as n1 != n2 */
+        result = 3;
+        for (size_t i = 0; i < nl; i++) {
+            if (_pa[i] ^ _pb[i]) {
+                /*
+                 * If we don't mutate result here, dead code elimination
+                 * we remove for loop.
+                 */
+                result = 4;
+            }
         }
     }
     return result;
diff --git a/ldap/servers/slapd/slapi-plugin.h 
b/ldap/servers/slapd/slapi-plugin.h
index 4566202..95cdcc0 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5862,7 +5862,7 @@ char *slapi_ch_smprintf(const char *fmt, ...)
  * \param n length in bytes of the content of p1 AND p2.
  * \return 0 on match. 1 on non-match. 2 on presence of NULL pointer in p1 or 
p2.
  */
-int slapi_ct_memcmp(const void *p1, const void *p2, size_t n);
+int32_t slapi_ct_memcmp(const void *p1, const void *p2, size_t n1, size_t n2);
 
 /*
  * syntax plugin routines
-- 
1.8.3.1


--- End Message ---
--- Begin Message ---
Source: 389-ds-base
Source-Version: 1.3.7.9-1

We believe that the bug you reported is fixed in the latest version of
389-ds-base, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 888...@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Timo Aaltonen <tjaal...@debian.org> (supplier of updated 389-ds-base package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmas...@ftp-master.debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Format: 1.8
Date: Mon, 05 Feb 2018 16:25:09 +0200
Source: 389-ds-base
Binary: 389-ds 389-ds-base-libs 389-ds-base-dev 389-ds-base python3-lib389 
python3-dirsrvtests
Architecture: source
Version: 1.3.7.9-1
Distribution: unstable
Urgency: medium
Maintainer: Debian 389ds Team 
<pkg-fedora-ds-maintain...@lists.alioth.debian.org>
Changed-By: Timo Aaltonen <tjaal...@debian.org>
Description:
 389-ds     - 389 Directory Server suite - metapackage
 389-ds-base - 389 Directory Server suite - server
 389-ds-base-dev - 389 Directory Server suite - development files
 389-ds-base-libs - 389 Directory Server suite - libraries
 python3-dirsrvtests - Python3 module for 389 Directory Server Continuous 
Integration te
 python3-lib389 - Python3 module for accessing and configuring the 389 
Directory Se
Closes: 888451 888452
Changes:
 389-ds-base (1.3.7.9-1) unstable; urgency=medium
 .
   * New upstream release.
     - CVE-2017-15134 (Closes: #888452)
   * patches: Fix CVE-2017-15135. (Closes: #888451)
   * tests: Add some debug output.
Checksums-Sha1:
 d6057d4029733987b58726d2086437d6612f2ece 2737 389-ds-base_1.3.7.9-1.dsc
 a3b49138c588c8389e547622ea62fa77e7f0005b 3573617 
389-ds-base_1.3.7.9.orig.tar.bz2
 efbccfd6e1b62487cfbde401335f08402e68bbb6 23664 
389-ds-base_1.3.7.9-1.debian.tar.xz
Checksums-Sha256:
 744149e318639702c9d55b6167901a72d0bb81904b1d7a3de60afbd0d097106f 2737 
389-ds-base_1.3.7.9-1.dsc
 fe9e7bee67ff6ce8b41d7e7c74dae79bd69711bcb488fe8c226e218357331e37 3573617 
389-ds-base_1.3.7.9.orig.tar.bz2
 7dcce3f6c1be57cb16f839cd60f2c61f3daa133e33e0e178a3643f23cf383198 23664 
389-ds-base_1.3.7.9-1.debian.tar.xz
Files:
 e7bd5b53d457f0c8067b9a316ac653e0 2737 net optional 389-ds-base_1.3.7.9-1.dsc
 1f40ad0aec80cc2b084a2914d2dd6370 3573617 net optional 
389-ds-base_1.3.7.9.orig.tar.bz2
 50979bbacef1c4705e2a93584cf9177e 23664 net optional 
389-ds-base_1.3.7.9-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBCAAGBQJaeGpRAAoJEMtwMWWoiYTcS7gP/jfcYJZcOxm95mEy03tQd+v8
wmSR2+vWQbHz+8Vl3HZZtepB1lDKu0YdvYKVGtJxdSNcZ3FSzhZT+rXrEb4cqWue
MYD1Y2njzK7GWrOXIE8Lx/wC4vFhzdsApxX0FVgpsW6HPGdB0ebG06c9gx1aK/Ol
nB+6WjgNOCp1FlqiypNhjzhDMKuLz9/hpNSL5VNVRXTeVdB8Lw9/0K47XMEKpYY6
9YnfnT1LgynPJHBanwPwUdK3NeEtpDgjKADAlfy7ozLndVA7ka2BjKYXZ7zBFHCt
YxQOBI6fp5QpiYjo7M5XTYxCobeQdmt9GhNajVrPvI9xFKEZJVqoYwEphsMvjEJZ
m4C5Ih646c9A6yA7HeZx54lpdUbAMwrb8DcMRS7lgAqwIEHQdgTt+ubPSyCfMy3c
nWlyBkYxTui/AL+i+lo7UooNGGbosQCsO7n+q2g3T0+MIAzV0gCEhEGvptLrIjjW
yWDJGp1j7Nl22A82/3bsYnUK/a5jhmJvaCdiivFr6QnVcrfRtXZY6CBErMlYbyEv
6+UoIHCOtkYjdJZRj6XaRdh9GYa7M0v2yrh0v5facqzfmoxcHTn59TYIT4vNtNZv
gCjCDKIijY28Om8niltDbOiw+OlNi2jjZG2N2MInw87fdrCGCi0rKk++RyOi/4Yl
2owN6Q/ctz1EGP90E92Q
=f6bA
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to