krb5 commit [krb5-1.22]: Fix krb5 GSS MIC verification

ghudson at mit.edu ghudson at mit.edu
Wed Aug 20 14:30:52 EDT 2025


https://github.com/krb5/krb5/commit/2531770c10115cb8b5ff529f813d86fa5a36db4c
commit 2531770c10115cb8b5ff529f813d86fa5a36db4c
Author: Greg Hudson <ghudson at mit.edu>
Date:   Sun Aug 17 02:55:40 2025 -0400

    Fix krb5 GSS MIC verification
    
    Commit 7ae0adcdf16687810f747e284c9fb571a561c5bd contains a pair of
    bugs that, in combination, result in the acceptance of MIC tokens with
    invalid checksums.
    
    In kg_verify_checksum_v3(), properly set bytes 4..7 to 0xFF in the
    composed token header for MIC tokens.  In verify_mic_v3(), properly
    check the return value of kg_verify_checksum_v3().  In t_invalid.c,
    test invalid MIC tokens by altering the bytes of a valid MIC.
    
    Reported by Francis Dupont.
    
    CVE-2025-57736:
    
    MIT krb5 release 1.22 incorrectly accepts krb5 GSS-API MIC tokens with
    invalid checksums.
    
    (cherry picked from commit 83cd76b11b069afbc6162edecb30096571e89dd5)
    
    ticket: 9181
    version_fixed: 1.22.1

 src/lib/gssapi/krb5/util_crypt.c | 10 +++++++---
 src/lib/gssapi/krb5/verify_mic.c | 11 ++++-------
 src/tests/gssapi/t_invalid.c     | 29 +++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
index 28411429b..386842e8a 100644
--- a/src/lib/gssapi/krb5/util_crypt.c
+++ b/src/lib/gssapi/krb5/util_crypt.c
@@ -322,12 +322,16 @@ kg_verify_checksum_v3(krb5_context context, krb5_key key, krb5_keyusage usage,
     uint8_t ckhdr[16];
     krb5_boolean valid;
 
-    /* Compose an RFC 4121 token header with EC and RRC set to 0. */
+    /*
+     * Compose an RFC 4121 token header for the checksum.  For a wrap token,
+     * the EC and RRC fields have the value 0 for the checksum operation,
+     * regardless of their values in the actual token (RFC 4121 section 4.2.4).
+     * For a MIC token, the corresponding four bytes have the value 0xFF.
+     */
     store_16_be(toktype, ckhdr);
     ckhdr[2] = flags;
     ckhdr[3] = 0xFF;
-    store_16_be(0, ckhdr + 4);
-    store_16_be(0, ckhdr + 6);
+    store_32_be((toktype == KG2_TOK_MIC_MSG) ? 0xFFFFFFFF : 0, ckhdr + 4);
     store_64_be(seqnum, ckhdr + 8);
 
     /* Verify the checksum over the data and composed header. */
diff --git a/src/lib/gssapi/krb5/verify_mic.c b/src/lib/gssapi/krb5/verify_mic.c
index 9852f4991..1c11d2016 100644
--- a/src/lib/gssapi/krb5/verify_mic.c
+++ b/src/lib/gssapi/krb5/verify_mic.c
@@ -90,7 +90,6 @@ verify_mic_v3(krb5_context context, OM_uint32 *minor_status,
               krb5_gss_ctx_id_rec *ctx, struct k5input *in,
               gss_buffer_t message)
 {
-    OM_uint32 status;
     krb5_keyusage usage;
     krb5_key key;
     krb5_cksumtype cksumtype;
@@ -124,12 +123,10 @@ verify_mic_v3(krb5_context context, OM_uint32 *minor_status,
     }
     assert(key != NULL);
 
-    status = kg_verify_checksum_v3(context, key, usage, cksumtype,
-                                   KG2_TOK_MIC_MSG, flags, seqnum,
-                                   message->value, message->length,
-                                   in->ptr, in->len);
-    if (status != GSS_S_COMPLETE)
-        return status;
+    if (!kg_verify_checksum_v3(context, key, usage, cksumtype, KG2_TOK_MIC_MSG,
+                               flags, seqnum, message->value, message->length,
+                               in->ptr, in->len))
+        return GSS_S_BAD_SIG;
 
     return g_seqstate_check(ctx->seqstate, seqnum);
 }
diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c
index c4a5a99ba..ecbf5ec21 100644
--- a/src/tests/gssapi/t_invalid.c
+++ b/src/tests/gssapi/t_invalid.c
@@ -397,6 +397,34 @@ test_iov_large_asn1_wrapper(gss_ctx_id_t ctx)
     free(iov[0].buffer.value);
 }
 
+static void
+test_cfx_verify_mic(gss_ctx_id_t ctx)
+{
+    OM_uint32 major, minor;
+    gss_buffer_desc message, token;
+    uint8_t msg[] = "message";
+    uint8_t mic[] = "\x04\x04\x00\xFF\xFF\xFF\xFF\xFF"
+        "\x00\x00\x00\x00\x00\x00\x00\x00\x97\xE9\x63\x3F\x9D\x82\x2B\x74"
+        "\x67\x94\x8A\xD0";
+    size_t i;
+
+    message.value = msg;
+    message.length = sizeof(msg) - 1;
+    token.value = mic;
+    token.length = sizeof(mic) - 1;
+
+    major = gss_verify_mic(&minor, ctx, &message, &token, NULL);
+    check_gsserr("gss_verify_mic", major, minor);
+
+    for (i = 0; i < token.length; i++) {
+        mic[i]++;
+        major = gss_verify_mic(&minor, ctx, &message, &token, NULL);
+        if (major != GSS_S_DEFECTIVE_TOKEN && major != GSS_S_BAD_SIG)
+            abort();
+        mic[i]--;
+    }
+}
+
 /* Process wrap and MIC tokens with incomplete headers. */
 static void
 test_short_header(gss_ctx_id_t ctx)
@@ -598,6 +626,7 @@ main(int argc, char **argv)
     test_cfx_short_plaintext(ctx, cfx_subkey);
     test_cfx_large_ec(ctx, cfx_subkey);
     test_iov_large_asn1_wrapper(ctx);
+    test_cfx_verify_mic(ctx);
     free_fake_context(ctx);
 
     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {


More information about the cvs-krb5 mailing list