Skip to content

Commit

Permalink
Fix integer overflows in PAC parsing
Browse files Browse the repository at this point in the history
In krb5_parse_pac(), check for buffer counts large enough to threaten
integer overflow in the header length and memory length calculations.
Avoid potential integer overflows when checking the length of each
buffer.  Credit to OSS-Fuzz for discovering one of the issues.

CVE-2022-42898:

In MIT krb5 releases 1.8 and later, an authenticated attacker may be
able to cause a KDC or kadmind process to crash by reading beyond the
bounds of allocated memory, creating a denial of service.  A
privileged attacker may similarly be able to cause a Kerberos or GSS
application service to crash.  On 32-bit platforms, an attacker can
also cause insufficient memory to be allocated for the result,
potentially leading to remote code execution in a KDC, kadmind, or GSS
or Kerberos application server process.  An attacker with the
privileges of a cross-realm KDC may be able to extract secrets from a
KDC process's memory by having them copied into the PAC of a new
ticket.

ticket: 9074 (new)
tags: pullup
target_version: 1.20-next
target_version: 1.19-next
  • Loading branch information
greghudson committed Nov 3, 2022
1 parent fa62bd3 commit ea92d2f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/lib/krb5/krb/pac.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "int-proto.h"
#include "authdata.h"

#define MAX_BUFFERS 4096

/* draft-brezak-win2k-krb-authz-00 */

/*
Expand Down Expand Up @@ -317,6 +319,9 @@ krb5_pac_parse(krb5_context context,
if (version != 0)
return EINVAL;

if (cbuffers < 1 || cbuffers > MAX_BUFFERS)
return ERANGE;

header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH);
if (len < header_len)
return ERANGE;
Expand Down Expand Up @@ -349,8 +354,8 @@ krb5_pac_parse(krb5_context context,
krb5_pac_free(context, pac);
return EINVAL;
}
if (buffer->Offset < header_len ||
buffer->Offset + buffer->cbBufferSize > len) {
if (buffer->Offset < header_len || buffer->Offset > len ||
buffer->cbBufferSize > len - buffer->Offset) {
krb5_pac_free(context, pac);
return ERANGE;
}
Expand Down
18 changes: 18 additions & 0 deletions src/lib/krb5/krb/t_pac.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,16 @@ static const unsigned char s4u_pac_ent_xrealm[] = {
0x8a, 0x81, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00
};

static const unsigned char fuzz1[] = {
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x06, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf5
};

static const unsigned char fuzz2[] = {
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x20, 0x20
};

static const char *s4u_principal = "w2k8u@ACME.COM";
static const char *s4u_enterprise = "w2k8u@abc@ACME.COM";

Expand Down Expand Up @@ -828,6 +838,14 @@ main(int argc, char **argv)
krb5_free_principal(context, sep);
}

/* Check problematic PACs found by fuzzing. */
ret = krb5_pac_parse(context, fuzz1, sizeof(fuzz1), &pac);
if (!ret)
err(context, ret, "krb5_pac_parse should have failed");
ret = krb5_pac_parse(context, fuzz2, sizeof(fuzz2), &pac);
if (!ret)
err(context, ret, "krb5_pac_parse should have failed");

/*
* Test empty free
*/
Expand Down

0 comments on commit ea92d2f

Please sign in to comment.