krb5 commit: Enforce lockdown bit in password change server

ghudson at mit.edu ghudson at mit.edu
Mon Nov 9 11:59:43 EST 2026


https://github.com/krb5/krb5/commit/d8248074bbd5c87d6415cba5dbb604a668197e28
commit d8248074bbd5c87d6415cba5dbb604a668197e28
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Oct 7 19:19:39 2026 -0400

    Enforce lockdown bit in password change server
    
    In schpw_util_wrapper(), reject password changes when the lockdown bit
    is set on the target principal.  Discovered by Claude and Ada Logics.
    
    CVE-2026-107884:
    
    In MIT krb5 release 1.15 and later, a client with kadmin
    administrative privileges can bypass the lockdown_keys attribute by
    using the password change protocol instead of the kadmin protocol.
    
    ticket: 9252 (new)
    tags: pullup
    target_version: 1.22-next

 src/kadmin/server/misc.c  | 28 +++++++++++++++++++---------
 src/kadmin/server/schpw.c |  1 +
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/src/kadmin/server/misc.c b/src/kadmin/server/misc.c
index 2d596e27f..acfeb16c0 100644
--- a/src/kadmin/server/misc.c
+++ b/src/kadmin/server/misc.c
@@ -20,6 +20,8 @@ schpw_util_wrapper(void *server_handle,
 {
     kadm5_ret_t                 ret;
     kadm5_server_handle_t       handle = server_handle;
+    kadm5_principal_ent_rec     rec;
+    int                         lockdown;
 
     /*
      * If no target is explicitly provided, then the target principal
@@ -42,18 +44,26 @@ schpw_util_wrapper(void *server_handle,
             return ret;
     }
 
-    if (auth(handle->context, OP_CPW, client, target,
-             NULL, NULL, NULL, NULL, 0)) {
-        ret = kadm5_chpass_principal_util(server_handle,
-                                          target,
-                                          new_pw, ret_pw,
-                                          msg_ret, msg_len);
-    } else {
-        ret = KADM5_AUTH_CHANGEPW;
+    if (!auth(handle->context, OP_CPW, client, target,
+              NULL, NULL, NULL, NULL, 0)) {
         strlcpy(msg_ret, "Unauthorized request", msg_len);
+        return KADM5_AUTH_CHANGEPW;
     }
 
-    return ret;
+    ret = kadm5_get_principal(handle, target, &rec, KADM5_ATTRIBUTES);
+    if (ret) {
+        strlcpy(msg_ret, "Target principal not found", msg_len);
+        return ret;
+    }
+    lockdown = (rec.attributes & KRB5_KDB_LOCKDOWN_KEYS) != 0;
+    kadm5_free_principal_ent(handle, &rec);
+    if (lockdown) {
+        strlcpy(msg_ret, "Principal keys are locked down", msg_len);
+        return KADM5_PROTECT_KEYS;
+    }
+
+    return kadm5_chpass_principal_util(server_handle, target, new_pw, ret_pw,
+                                       msg_ret, msg_len);
 }
 
 kadm5_ret_t
diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c
index 1d7183f7a..c2c03e76c 100644
--- a/src/kadmin/server/schpw.c
+++ b/src/kadmin/server/schpw.c
@@ -248,6 +248,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm,
     }
     switch (ret) {
     case KADM5_AUTH_CHANGEPW:
+    case KADM5_PROTECT_KEYS:
         numresult = KRB5_KPASSWD_ACCESSDENIED;
         break;
     case KADM5_AUTH_INITIAL:


More information about the cvs-krb5 mailing list