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