Blame SOURCES/Fix-integer-overflows-in-PAC-parsing.patch

0e708d
From 21d7d94a16ed0be6e1fb101679bf9446b1163d44 Mon Sep 17 00:00:00 2001
0e708d
From: Greg Hudson <ghudson@mit.edu>
0e708d
Date: Mon, 17 Oct 2022 20:25:11 -0400
0e708d
Subject: [PATCH] Fix integer overflows in PAC parsing
0e708d
0e708d
In krb5_parse_pac(), check for buffer counts large enough to threaten
0e708d
integer overflow in the header length and memory length calculations.
0e708d
Avoid potential integer overflows when checking the length of each
0e708d
buffer.
0e708d
0e708d
CVE-2022-42898:
0e708d
0e708d
In MIT krb5 releases 1.8 and later, an authenticated attacker may be
0e708d
able to cause a KDC or kadmind process to crash by reading beyond the
0e708d
bounds of allocated memory, creating a denial of service.  A
0e708d
privileged attacker may similarly be able to cause a Kerberos or GSS
0e708d
application service to crash.  On 32-bit platforms, an attacker can
0e708d
also cause insufficient memory to be allocated for the result,
0e708d
potentially leading to remote code execution in a KDC, kadmind, or GSS
0e708d
or Kerberos application server process.  An attacker with the
0e708d
privileges of a cross-realm KDC may be able to extract secrets from
0e708d
the KDC process's memory by having them copied into the PAC of a new
0e708d
ticket.
0e708d
0e708d
ticket: 9074 (new)
0e708d
tags: pullup
0e708d
target_version: 1.20-next
0e708d
target_version: 1.19-next
0e708d
---
0e708d
 src/lib/krb5/krb/pac.c   |  9 +++++++--
0e708d
 src/lib/krb5/krb/t_pac.c | 18 ++++++++++++++++++
0e708d
 2 files changed, 25 insertions(+), 2 deletions(-)
0e708d
0e708d
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
0e708d
index 950beda657..2e844d499b 100644
0e708d
--- a/src/lib/krb5/krb/pac.c
0e708d
+++ b/src/lib/krb5/krb/pac.c
0e708d
@@ -29,6 +29,8 @@
0e708d
 
0e708d
 /* draft-brezak-win2k-krb-authz-00 */
0e708d
 
0e708d
+#define MAX_BUFFERS 4096
0e708d
+
0e708d
 /*
0e708d
  * Add a buffer to the provided PAC and update header.
0e708d
  */
0e708d
@@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context,
0e708d
     if (version != 0)
0e708d
         return EINVAL;
0e708d
 
0e708d
+    if (cbuffers < 1 || cbuffers > MAX_BUFFERS)
0e708d
+        return ERANGE;
0e708d
+
0e708d
     header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
0e708d
     if (len < header_len)
0e708d
         return ERANGE;
0e708d
@@ -348,8 +353,8 @@ krb5_pac_parse(krb5_context context,
0e708d
             krb5_pac_free(context, pac);
0e708d
             return EINVAL;
0e708d
         }
0e708d
-        if (buffer->Offset < header_len ||
0e708d
-            buffer->Offset + buffer->cbBufferSize > len) {
0e708d
+        if (buffer->Offset < header_len || buffer->Offset > len ||
0e708d
+            buffer->cbBufferSize > len - buffer->Offset) {
0e708d
             krb5_pac_free(context, pac);
0e708d
             return ERANGE;
0e708d
         }
0e708d
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
0e708d
index ee47152ee4..ccd165380d 100644
0e708d
--- a/src/lib/krb5/krb/t_pac.c
0e708d
+++ b/src/lib/krb5/krb/t_pac.c
0e708d
@@ -431,6 +431,16 @@ static const unsigned char s4u_pac_ent_xrealm[] = {
0e708d
     0x8a, 0x81, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00
0e708d
 };
0e708d
 
0e708d
+static const unsigned char fuzz1[] = {
0e708d
+    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0e708d
+    0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5
0e708d
+};
0e708d
+
0e708d
+static const unsigned char fuzz2[] = {
0e708d
+    0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0e708d
+    0x20, 0x20
0e708d
+};
0e708d
+
0e708d
 static const char *s4u_principal = "w2k8u@ACME.COM";
0e708d
 static const char *s4u_enterprise = "w2k8u@abc@ACME.COM";
0e708d
 
0e708d
@@ -646,6 +656,14 @@ main(int argc, char **argv)
0e708d
         krb5_free_principal(context, sep);
0e708d
     }
0e708d
 
0e708d
+    /* Check problematic PACs found by fuzzing. */
0e708d
+    ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac;;
0e708d
+    if (!ret)
0e708d
+        err(context, ret, "krb5_pac_parse should have failed");
0e708d
+    ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac;;
0e708d
+    if (!ret)
0e708d
+        err(context, ret, "krb5_pac_parse should have failed");
0e708d
+
0e708d
     /*
0e708d
      * Test empty free
0e708d
      */
0e708d
-- 
0e708d
2.37.3
0e708d