|
| 1 | +From 246f4b4deab5c635063d49c3d41951a7ab4a3a59 Mon Sep 17 00:00:00 2001 |
| 2 | +From: archana25-ms <v-shettigara@microsoft.com> |
| 3 | +Date: Tue, 24 Jun 2025 12:44:27 +0000 |
| 4 | +Subject: [PATCH] Address CVE-2025-3576 |
| 5 | +Upstream Patch Reference: |
| 6 | +1. https://github.com/krb5/krb5/commit/1b57a4d134bbd0e7c52d5885a92eccc815726463 |
| 7 | +2. https://github.com/krb5/krb5/commit/2cbd847e0e92bc4e219b65c770ae33f851b22afc |
| 8 | + |
| 9 | + |
| 10 | +--- |
| 11 | + doc/admin/conf_files/krb5_conf.rst | 12 ++++++++++++ |
| 12 | + doc/admin/enctypes.rst | 23 +++++++++++++++++++--- |
| 13 | + src/include/k5-int.h | 4 ++++ |
| 14 | + src/kdc/kdc_util.c | 14 ++++++++++++++ |
| 15 | + src/lib/krb5/krb/get_in_tkt.c | 31 +++++++++++++++++++----------- |
| 16 | + src/lib/krb5/krb/init_ctx.c | 10 ++++++++++ |
| 17 | + src/tests/gssapi/t_enctypes.py | 3 ++- |
| 18 | + src/tests/t_etype_info.py | 2 +- |
| 19 | + src/tests/t_keyrollover.py | 6 +++--- |
| 20 | + src/tests/t_sesskeynego.py | 28 +++++++++++++++++++++++++-- |
| 21 | + src/util/k5test.py | 4 ++-- |
| 22 | + 11 files changed, 114 insertions(+), 23 deletions(-) |
| 23 | + |
| 24 | +diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst |
| 25 | +index 6751759..e95fc53 100644 |
| 26 | +--- a/doc/admin/conf_files/krb5_conf.rst |
| 27 | ++++ b/doc/admin/conf_files/krb5_conf.rst |
| 28 | +@@ -95,6 +95,18 @@ Additionally, krb5.conf may include any of the relations described in |
| 29 | + |
| 30 | + The libdefaults section may contain any of the following relations: |
| 31 | + |
| 32 | ++**allow_des3** |
| 33 | ++ Permit the KDC to issue tickets with des3-cbc-sha1 session keys. |
| 34 | ++ In future releases, this flag will allow des3-cbc-sha1 to be used |
| 35 | ++ at all. The default value for this tag is false. (Added in |
| 36 | ++ release 1.21.) |
| 37 | ++ |
| 38 | ++**allow_rc4** |
| 39 | ++ Permit the KDC to issue tickets with arcfour-hmac session keys. |
| 40 | ++ In future releases, this flag will allow arcfour-hmac to be used |
| 41 | ++ at all. The default value for this tag is false. (Added in |
| 42 | ++ release 1.21.) |
| 43 | ++ |
| 44 | + **allow_weak_crypto** |
| 45 | + If this flag is set to false, then weak encryption types (as noted |
| 46 | + in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered |
| 47 | +diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst |
| 48 | +index 694922c..dce19ad 100644 |
| 49 | +--- a/doc/admin/enctypes.rst |
| 50 | ++++ b/doc/admin/enctypes.rst |
| 51 | +@@ -48,12 +48,15 @@ Session key selection |
| 52 | + The KDC chooses the session key enctype by taking the intersection of |
| 53 | + its **permitted_enctypes** list, the list of long-term keys for the |
| 54 | + most recent kvno of the service, and the client's requested list of |
| 55 | +-enctypes. |
| 56 | ++enctypes. Starting in krb5-1.21, all services are assumed to support |
| 57 | ++aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session |
| 58 | ++keys will not be issued by default. |
| 59 | + |
| 60 | + Starting in krb5-1.11, it is possible to set a string attribute on a |
| 61 | + service principal to control what session key enctypes the KDC may |
| 62 | +-issue for service tickets for that principal. See :ref:`set_string` |
| 63 | +-in :ref:`kadmin(1)` for details. |
| 64 | ++issue for service tickets for that principal, overriding the service's |
| 65 | ++long-term keys and the assumption of aes256-cts-hmac-sha1-96 support. |
| 66 | ++See :ref:`set_string` in :ref:`kadmin(1)` for details. |
| 67 | + |
| 68 | + |
| 69 | + Choosing enctypes for a service |
| 70 | +@@ -87,6 +90,20 @@ affect how enctypes are chosen. |
| 71 | + acceptable risk for your environment and the weak enctypes are |
| 72 | + required for backward compatibility. |
| 73 | + |
| 74 | ++**allow_des3** |
| 75 | ++ was added in release 1.21 and defaults to *false*. Unless this |
| 76 | ++ flag is set to *true*, the KDC will not issue tickets with |
| 77 | ++ des3-cbc-sha1 session keys. In a future release, this flag will |
| 78 | ++ control whether des3-cbc-sha1 is permitted in similar fashion to |
| 79 | ++ weak enctypes. |
| 80 | ++ |
| 81 | ++**allow_rc4** |
| 82 | ++ was added in release 1.21 and defaults to *false*. Unless this |
| 83 | ++ flag is set to *true*, the KDC will not issue tickets with |
| 84 | ++ arcfour-hmac session keys. In a future release, this flag will |
| 85 | ++ control whether arcfour-hmac is permitted in similar fashion to |
| 86 | ++ weak enctypes. |
| 87 | ++ |
| 88 | + **permitted_enctypes** |
| 89 | + controls the set of enctypes that a service will permit for |
| 90 | + session keys and for ticket and authenticator encryption. The KDC |
| 91 | +diff --git a/src/include/k5-int.h b/src/include/k5-int.h |
| 92 | +index cf52425..e778340 100644 |
| 93 | +--- a/src/include/k5-int.h |
| 94 | ++++ b/src/include/k5-int.h |
| 95 | +@@ -180,6 +180,8 @@ typedef unsigned char u_char; |
| 96 | + * matches the variable name. Keep these alphabetized. */ |
| 97 | + #define KRB5_CONF_ACL_FILE "acl_file" |
| 98 | + #define KRB5_CONF_ADMIN_SERVER "admin_server" |
| 99 | ++#define KRB5_CONF_ALLOW_DES3 "allow_des3" |
| 100 | ++#define KRB5_CONF_ALLOW_RC4 "allow_rc4" |
| 101 | + #define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto" |
| 102 | + #define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local" |
| 103 | + #define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names" |
| 104 | +@@ -1257,6 +1259,8 @@ struct _krb5_context { |
| 105 | + struct _kdb_log_context *kdblog_context; |
| 106 | + |
| 107 | + krb5_boolean allow_weak_crypto; |
| 108 | ++ krb5_boolean allow_des3; |
| 109 | ++ krb5_boolean allow_rc4; |
| 110 | + krb5_boolean ignore_acceptor_hostname; |
| 111 | + krb5_boolean enforce_ok_as_delegate; |
| 112 | + enum dns_canonhost dns_canonicalize_hostname; |
| 113 | +diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c |
| 114 | +index 60f30c4..866bc2c 100644 |
| 115 | +--- a/src/kdc/kdc_util.c |
| 116 | ++++ b/src/kdc/kdc_util.c |
| 117 | +@@ -929,6 +929,10 @@ dbentry_supports_enctype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, |
| 118 | + free(etypes_str); |
| 119 | + free(etypes); |
| 120 | + |
| 121 | ++ /* Assume every server without a session_enctypes attribute supports |
| 122 | ++ * aes256-cts-hmac-sha1-96. */ |
| 123 | ++ if (enctype == ENCTYPE_AES256_CTS_HMAC_SHA1_96) |
| 124 | ++ return TRUE; |
| 125 | + /* Assume the server supports any enctype it has a long-term key for. */ |
| 126 | + return !krb5_dbe_find_enctype(kdc_context, server, enctype, -1, 0, &datap); |
| 127 | + } |
| 128 | +@@ -951,6 +955,16 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server, |
| 129 | + if (!krb5_is_permitted_enctype(kdc_context, ktype[i])) |
| 130 | + continue; |
| 131 | + |
| 132 | ++ /* |
| 133 | ++ * Prevent these deprecated enctypes from being used as session keys |
| 134 | ++ * unless they are explicitly allowed. In the future they will be more |
| 135 | ++ * comprehensively disabled and eventually removed. |
| 136 | ++ */ |
| 137 | ++ if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3) |
| 138 | ++ continue; |
| 139 | ++ if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4) |
| 140 | ++ continue; |
| 141 | ++ |
| 142 | + if (dbentry_supports_enctype(kdc_active_realm, server, ktype[i])) |
| 143 | + return ktype[i]; |
| 144 | + } |
| 145 | +diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c |
| 146 | +index 5695187..71e610e 100644 |
| 147 | +--- a/src/lib/krb5/krb/get_in_tkt.c |
| 148 | ++++ b/src/lib/krb5/krb/get_in_tkt.c |
| 149 | +@@ -1589,22 +1589,31 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, |
| 150 | + (*prompter)(context, data, 0, banner, 0, 0); |
| 151 | + } |
| 152 | + |
| 153 | +-/* Display a warning via the prompter if des3-cbc-sha1 was used for either the |
| 154 | +- * reply key or the session key. */ |
| 155 | ++/* Display a warning via the prompter if a deprecated enctype was used for |
| 156 | ++ * either the reply key or the session key. */ |
| 157 | + static void |
| 158 | +-warn_des3(krb5_context context, krb5_init_creds_context ctx, |
| 159 | +- krb5_enctype as_key_enctype) |
| 160 | ++warn_deprecated(krb5_context context, krb5_init_creds_context ctx, |
| 161 | ++ krb5_enctype as_key_enctype) |
| 162 | + { |
| 163 | +- const char *banner; |
| 164 | ++ krb5_enctype etype; |
| 165 | ++ char encbuf[128], banner[256]; |
| 166 | + |
| 167 | +- if (as_key_enctype != ENCTYPE_DES3_CBC_SHA1 && |
| 168 | +- ctx->cred.keyblock.enctype != ENCTYPE_DES3_CBC_SHA1) |
| 169 | +- return; |
| 170 | + if (ctx->prompter == NULL) |
| 171 | + return; |
| 172 | + |
| 173 | +- banner = _("Warning: encryption type des3-cbc-sha1 used for " |
| 174 | +- "authentication is weak and will be disabled"); |
| 175 | ++ if (krb5int_c_deprecated_enctype(as_key_enctype)) |
| 176 | ++ etype = as_key_enctype; |
| 177 | ++ else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype)) |
| 178 | ++ etype = ctx->cred.keyblock.enctype; |
| 179 | ++ else |
| 180 | ++ return; |
| 181 | ++ |
| 182 | ++ if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0) |
| 183 | ++ return; |
| 184 | ++ snprintf(banner, sizeof(banner), |
| 185 | ++ _("Warning: encryption type %s used for authentication is " |
| 186 | ++ "deprecated and will be disabled"), encbuf); |
| 187 | ++ |
| 188 | + /* PROMPTER_INVOCATION */ |
| 189 | + (*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL); |
| 190 | + } |
| 191 | +@@ -1822,7 +1831,7 @@ init_creds_step_reply(krb5_context context, |
| 192 | + ctx->complete = TRUE; |
| 193 | + warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data, |
| 194 | + ctx->in_tkt_service, ctx->reply); |
| 195 | +- warn_des3(context, ctx, encrypting_key.enctype); |
| 196 | ++ warn_deprecated(context, ctx, encrypting_key.enctype); |
| 197 | + |
| 198 | + cleanup: |
| 199 | + krb5_free_pa_data(context, kdc_padata); |
| 200 | +diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c |
| 201 | +index aa35baa..f8de175 100644 |
| 202 | +--- a/src/lib/krb5/krb/init_ctx.c |
| 203 | ++++ b/src/lib/krb5/krb/init_ctx.c |
| 204 | +@@ -227,6 +227,16 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags, |
| 205 | + goto cleanup; |
| 206 | + ctx->allow_weak_crypto = tmp; |
| 207 | + |
| 208 | ++ retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp); |
| 209 | ++ if (retval) |
| 210 | ++ goto cleanup; |
| 211 | ++ ctx->allow_des3 = tmp; |
| 212 | ++ |
| 213 | ++ retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp); |
| 214 | ++ if (retval) |
| 215 | ++ goto cleanup; |
| 216 | ++ ctx->allow_rc4 = tmp; |
| 217 | ++ |
| 218 | + retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp); |
| 219 | + if (retval) |
| 220 | + goto cleanup; |
| 221 | +diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py |
| 222 | +index 7494d7f..f5f1184 100755 |
| 223 | +--- a/src/tests/gssapi/t_enctypes.py |
| 224 | ++++ b/src/tests/gssapi/t_enctypes.py |
| 225 | +@@ -18,7 +18,8 @@ d_rc4 = 'DEPRECATED:arcfour-hmac' |
| 226 | + # These tests make assumptions about the default enctype lists, so set |
| 227 | + # them explicitly rather than relying on the library defaults. |
| 228 | + supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' |
| 229 | +-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4'}, |
| 230 | ++conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4', |
| 231 | ++ 'allow_des3': 'true', 'allow_rc4': 'true'}, |
| 232 | + 'realms': {'$realm': {'supported_enctypes': supp}}} |
| 233 | + realm = K5Realm(krb5_conf=conf) |
| 234 | + shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) |
| 235 | +diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py |
| 236 | +index c982508..38cf96c 100644 |
| 237 | +--- a/src/tests/t_etype_info.py |
| 238 | ++++ b/src/tests/t_etype_info.py |
| 239 | +@@ -1,7 +1,7 @@ |
| 240 | + from k5test import * |
| 241 | + |
| 242 | + supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' |
| 243 | +-conf = {'libdefaults': {'allow_weak_crypto': 'true'}, |
| 244 | ++conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'}, |
| 245 | + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} |
| 246 | + realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) |
| 247 | + |
| 248 | +diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py |
| 249 | +index 2c825a6..e9840df 100755 |
| 250 | +--- a/src/tests/t_keyrollover.py |
| 251 | ++++ b/src/tests/t_keyrollover.py |
| 252 | +@@ -22,9 +22,9 @@ realm.run([kvno, princ1]) |
| 253 | + realm.run([kadminl, 'purgekeys', realm.krbtgt_princ]) |
| 254 | + # Make sure an old TGT fails after purging old TGS key. |
| 255 | + realm.run([kvno, princ2], expected_code=1) |
| 256 | +-et = "aes128-cts-hmac-sha256-128" |
| 257 | +-msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \ |
| 258 | +- (realm.realm, realm.realm, et, et) |
| 259 | ++msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ |
| 260 | ++ 'aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha256-128' % \ |
| 261 | ++ (realm.realm, realm.realm) |
| 262 | + realm.run([klist, '-e'], expected_msg=msg) |
| 263 | + |
| 264 | + # Check that new key actually works. |
| 265 | +diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py |
| 266 | +index 9024aee..5a21361 100755 |
| 267 | +--- a/src/tests/t_sesskeynego.py |
| 268 | ++++ b/src/tests/t_sesskeynego.py |
| 269 | +@@ -25,6 +25,8 @@ conf3 = {'libdefaults': { |
| 270 | + 'default_tkt_enctypes': 'aes128-cts', |
| 271 | + 'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}} |
| 272 | + conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}} |
| 273 | ++conf5 = {'libdefaults': {'allow_rc4': 'true'}} |
| 274 | ++conf6 = {'libdefaults': {'allow_des3': 'true'}} |
| 275 | + # Test with client request and session_enctypes preferring aes128, but |
| 276 | + # aes256 long-term key. |
| 277 | + realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False) |
| 278 | +@@ -54,10 +56,12 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes', |
| 279 | + 'aes128-cts,aes256-cts']) |
| 280 | + test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') |
| 281 | + |
| 282 | +-# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term. |
| 283 | ++# 3b: Skip RC4 (as the KDC does not allow it for session keys by |
| 284 | ++# default) and negotiate aes128-cts session key, with only an aes256 |
| 285 | ++# long-term service key. |
| 286 | + realm.run([kadminl, 'setstr', 'server', 'session_enctypes', |
| 287 | + 'rc4-hmac,aes128-cts,aes256-cts']) |
| 288 | +-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') |
| 289 | ++test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') |
| 290 | + realm.stop() |
| 291 | + |
| 292 | + # 4: Check that permitted_enctypes is a default for session key enctypes. |
| 293 | +@@ -67,4 +71,24 @@ realm.run([kvno, 'user'], |
| 294 | + expected_trace=('etypes requested in TGS request: aes256-cts',)) |
| 295 | + realm.stop() |
| 296 | + |
| 297 | ++# 5: allow_rc4 permits negotiation of rc4-hmac session key. |
| 298 | ++realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False) |
| 299 | ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) |
| 300 | ++realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac']) |
| 301 | ++test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') |
| 302 | ++realm.stop() |
| 303 | ++ |
| 304 | ++# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key. |
| 305 | ++realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False) |
| 306 | ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) |
| 307 | ++realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1']) |
| 308 | ++test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96') |
| 309 | ++realm.stop() |
| 310 | ++ |
| 311 | ++# 7: default config negotiates aes256-sha1 session key for RC4-only service. |
| 312 | ++realm = K5Realm(create_host=False, get_creds=False) |
| 313 | ++realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server']) |
| 314 | ++test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac') |
| 315 | ++realm.stop() |
| 316 | ++ |
| 317 | + success('sesskeynego') |
| 318 | +diff --git a/src/util/k5test.py b/src/util/k5test.py |
| 319 | +index 6afe4b9..bdad1e6 100644 |
| 320 | +--- a/src/util/k5test.py |
| 321 | ++++ b/src/util/k5test.py |
| 322 | +@@ -1280,14 +1280,14 @@ _passes = [ |
| 323 | + |
| 324 | + # Exercise the DES3 enctype. |
| 325 | + ('des3', None, |
| 326 | +- {'libdefaults': {'permitted_enctypes': 'des3'}}, |
| 327 | ++ {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}}, |
| 328 | + {'realms': {'$realm': { |
| 329 | + 'supported_enctypes': 'des3-cbc-sha1:normal', |
| 330 | + 'master_key_type': 'des3-cbc-sha1'}}}), |
| 331 | + |
| 332 | + # Exercise the arcfour enctype. |
| 333 | + ('arcfour', None, |
| 334 | +- {'libdefaults': {'permitted_enctypes': 'rc4'}}, |
| 335 | ++ {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}}, |
| 336 | + {'realms': {'$realm': { |
| 337 | + 'supported_enctypes': 'arcfour-hmac:normal', |
| 338 | + 'master_key_type': 'arcfour-hmac'}}}), |
| 339 | +-- |
| 340 | +2.45.3 |
| 341 | + |
0 commit comments