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

24fa38
From 5741c46c084513d4d6b04e1e6abf810dbd996591 Mon Sep 17 00:00:00 2001
24fa38
From: Greg Hudson <ghudson@mit.edu>
24fa38
Date: Mon, 17 Oct 2022 20:25:11 -0400
24fa38
Subject: [PATCH] Fix integer overflows in PAC parsing
24fa38
24fa38
In krb5_parse_pac(), check for buffer counts large enough to threaten
24fa38
integer overflow in the header length and memory length calculations.
24fa38
Avoid potential integer overflows when checking the length of each
24fa38
buffer.
24fa38
24fa38
CVE-2022-42898:
24fa38
24fa38
In MIT krb5 releases 1.8 and later, an authenticated attacker may be
24fa38
able to cause a KDC or kadmind process to crash by reading beyond the
24fa38
bounds of allocated memory, creating a denial of service.  A
24fa38
privileged attacker may similarly be able to cause a Kerberos or GSS
24fa38
application service to crash.  On 32-bit platforms, an attacker can
24fa38
also cause insufficient memory to be allocated for the result,
24fa38
potentially leading to remote code execution in a KDC, kadmind, or GSS
24fa38
or Kerberos application server process.  An attacker with the
24fa38
privileges of a cross-realm KDC may be able to extract secrets from
24fa38
the KDC process's memory by having them copied into the PAC of a new
24fa38
ticket.
24fa38
24fa38
ticket: 9074 (new)
24fa38
tags: pullup
24fa38
target_version: 1.20-next
24fa38
target_version: 1.19-next
24fa38
---
24fa38
 src/lib/krb5/krb/pac.c   |  9 +++++++--
24fa38
 src/lib/krb5/krb/t_pac.c | 18 ++++++++++++++++++
24fa38
 2 files changed, 25 insertions(+), 2 deletions(-)
24fa38
24fa38
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
24fa38
index c70585a9eb..b0baa01930 100644
24fa38
--- a/src/lib/krb5/krb/pac.c
24fa38
+++ b/src/lib/krb5/krb/pac.c
24fa38
@@ -27,6 +27,8 @@
24fa38
 #include "k5-int.h"
24fa38
 #include "authdata.h"
24fa38
 
24fa38
+#define MAX_BUFFERS 4096
24fa38
+
24fa38
 /* draft-brezak-win2k-krb-authz-00 */
24fa38
 
24fa38
 /*
24fa38
@@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context,
24fa38
     if (version != 0)
24fa38
         return EINVAL;
24fa38
 
24fa38
+    if (cbuffers < 1 || cbuffers > MAX_BUFFERS)
24fa38
+        return ERANGE;
24fa38
+
24fa38
     header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
24fa38
     if (len < header_len)
24fa38
         return ERANGE;
24fa38
@@ -348,8 +353,8 @@ krb5_pac_parse(krb5_context context,
24fa38
             krb5_pac_free(context, pac);
24fa38
             return EINVAL;
24fa38
         }
24fa38
-        if (buffer->Offset < header_len ||
24fa38
-            buffer->Offset + buffer->cbBufferSize > len) {
24fa38
+        if (buffer->Offset < header_len || buffer->Offset > len ||
24fa38
+            buffer->cbBufferSize > len - buffer->Offset) {
24fa38
             krb5_pac_free(context, pac);
24fa38
             return ERANGE;
24fa38
         }
24fa38
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
24fa38
index 61fb51a98a..d7342bff9c 100644
24fa38
--- a/src/lib/krb5/krb/t_pac.c
24fa38
+++ b/src/lib/krb5/krb/t_pac.c
24fa38
@@ -96,6 +96,16 @@ static const krb5_keyblock member_keyblock = {
24fa38
 static time_t authtime = 1120440609;
24fa38
 static const char *user = "w2003final$@WIN2K3.THINKER.LOCAL";
24fa38
 
24fa38
+static const unsigned char fuzz1[] = {
24fa38
+    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
24fa38
+    0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5
24fa38
+};
24fa38
+
24fa38
+static const unsigned char fuzz2[] = {
24fa38
+    0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
24fa38
+    0x20, 0x20
24fa38
+};
24fa38
+
24fa38
 #if !defined(__cplusplus) && (__GNUC__ > 2)
24fa38
 static void err(krb5_context ctx, krb5_error_code code, const char *fmt, ...)
24fa38
     __attribute__((__format__(__printf__, 3, 0)));
24fa38
@@ -227,6 +237,14 @@ main(int argc, char **argv)
24fa38
 
24fa38
     krb5_pac_free(context, pac);
24fa38
 
24fa38
+    /* Check problematic PACs found by fuzzing. */
24fa38
+    ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac;;
24fa38
+    if (!ret)
24fa38
+        err(context, ret, "krb5_pac_parse should have failed");
24fa38
+    ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac;;
24fa38
+    if (!ret)
24fa38
+        err(context, ret, "krb5_pac_parse should have failed");
24fa38
+
24fa38
     /*
24fa38
      * Test empty free
24fa38
      */
24fa38
-- 
24fa38
2.37.3
24fa38