Commit c29e49eb authored by Natanael Copa's avatar Natanael Copa

main/heimdal: security fix for CVE-2019-12098

fixes #10555
parent f9f4e0e8
......@@ -3,7 +3,7 @@
pkgname=heimdal
pkgver=7.4.0
_ver=${pkgver/_rc/rc}
pkgrel=3
pkgrel=4
pkgdesc="An implementation of Kerberos 5"
arch="all"
url="http://www.h5l.org/"
......@@ -24,10 +24,13 @@ source="https://github.com/heimdal/heimdal/releases/download/heimdal-$pkgver/hei
heimdal_missing-include.patch
CVE-2017-17439.patch
CVE-2018-16860.patch
CVE-2019-12098.patch
"
builddir="$srcdir/$pkgname-$_ver"
# secfixes:
# 7.4.0-r4:
# - CVE-2019-12098
# 7.4.0-r3:
# - CVE-2018-16860
# 7.4.0-r2:
......@@ -134,4 +137,5 @@ abee8390632fa775e74900d09e5c72b02fe4f9616b43cc8d0a76175486ed6d4707fb3ce4d06ceb09
2a6b20588a86a9ea3c35209b96ef2da0b39bc3112aec1505e69a60efc9ffb9ddc1d0dbdfaf864142e9d2f81da3d2653de56d6ffa01871c20fde17e4642625c56 005_all_heimdal-suid_fix.patch
e89efdc942c512363aac1d9797c6bf622324e9200e282bc5ed680300b9e1b39a4ea20f059cdac8f22f972eb0af0e625fd41f267ebcafcfec0aaa81192aff79c1 heimdal_missing-include.patch
66f92a3f0c68c7ff1f842b11ab456c94dd9fb2951b2dbb31fc4b1364d591687facd88aafadb0971a8156424470a65440111077ca02c064bdadd7490f671774b1 CVE-2017-17439.patch
36738795eb3478b55790bf1927f85a421b13b6b47dcc273daeb6630c39a4e1c1258148fa0e9f004ae59a9ac89caf54cb25efedb417e852e42a2c32d02e43fd56 CVE-2018-16860.patch"
36738795eb3478b55790bf1927f85a421b13b6b47dcc273daeb6630c39a4e1c1258148fa0e9f004ae59a9ac89caf54cb25efedb417e852e42a2c32d02e43fd56 CVE-2018-16860.patch
4cb6a268e65f11d606d72c054ffcc4bf5e4d96c15d08db0e77b9b97447a6b96d6947427d7041742221d98e86b8fa59cdb939beb541446c1136125a9528e9bc3d CVE-2019-12098.patch"
From 2f7f3d9960aa6ea21358bdf3687cee5149aa35cf Mon Sep 17 00:00:00 2001
From: Luke Howard <lukeh@padl.com>
Date: Tue, 7 May 2019 13:15:15 +1000
Subject: [PATCH] CVE-2019-12098: krb5: always confirm PA-PKINIT-KX for anon
PKINIT
RFC8062 Section 7 requires verification of the PA-PKINIT-KX key excahnge
when anonymous PKINIT is used. Failure to do so can permit an active
attacker to become a man-in-the-middle.
Introduced by a1ef548600c5bb51cf52a9a9ea12676506ede19f. First tagged
release Heimdal 1.4.0.
CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N (4.8)
Change-Id: I6cc1c0c24985936468af08693839ac6c3edda133
Signed-off-by: Jeffrey Altman <jaltman@auristor.com>
Approved-by: Jeffrey Altman <jaltman@auritor.com>
(cherry picked from commit 38c797e1ae9b9c8f99ae4aa2e73957679031fd2b)
---
lib/krb5/init_creds_pw.c | 20 +++++++++
lib/krb5/krb5_locl.h | 1 +
lib/krb5/pkinit.c | 92 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+)
diff --git a/lib/krb5/init_creds_pw.c b/lib/krb5/init_creds_pw.c
index 1eece1760d..9ec07d0609 100644
--- a/lib/krb5/init_creds_pw.c
+++ b/lib/krb5/init_creds_pw.c
@@ -2267,6 +2267,26 @@ krb5_init_creds_step(krb5_context context,
&ctx->req_buffer,
NULL,
NULL);
+ if (ret == 0 && ctx->pk_init_ctx) {
+ PA_DATA *pa_pkinit_kx;
+ int idx = 0;
+
+ pa_pkinit_kx =
+ krb5_find_padata(rep.kdc_rep.padata->val,
+ rep.kdc_rep.padata->len,
+ KRB5_PADATA_PKINIT_KX,
+ &idx);
+
+ ret = _krb5_pk_kx_confirm(context, ctx->pk_init_ctx,
+ ctx->fast_state.reply_key,
+ &ctx->cred.session,
+ pa_pkinit_kx);
+ if (ret)
+ krb5_set_error_message(context, ret,
+ N_("Failed to confirm PA-PKINIT-KX", ""));
+ else if (pa_pkinit_kx != NULL)
+ ctx->ic_flags |= KRB5_INIT_CREDS_PKINIT_KX_VALID;
+ }
if (ret == 0)
ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part);
diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h
index 9d77b9f8a3..f61b66e999 100644
--- a/lib/krb5/krb5_locl.h
+++ b/lib/krb5/krb5_locl.h
@@ -208,6 +208,7 @@ struct _krb5_get_init_creds_opt_private {
#define KRB5_INIT_CREDS_CANONICALIZE 1
#define KRB5_INIT_CREDS_NO_C_CANON_CHECK 2
#define KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK 4
+#define KRB5_INIT_CREDS_PKINIT_KX_VALID 32
struct {
krb5_gic_process_last_req func;
void *ctx;
diff --git a/lib/krb5/pkinit.c b/lib/krb5/pkinit.c
index b16ee69d3c..e178242ea3 100644
--- a/lib/krb5/pkinit.c
+++ b/lib/krb5/pkinit.c
@@ -1220,6 +1220,98 @@ pk_rd_pa_reply_enckey(krb5_context context,
return ret;
}
+/*
+ * RFC 8062 section 7:
+ *
+ * The client then decrypts the KDC contribution key and verifies that
+ * the ticket session key in the returned ticket is the combined key of
+ * the KDC contribution key and the reply key.
+ */
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_pk_kx_confirm(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ krb5_keyblock *reply_key,
+ krb5_keyblock *session_key,
+ PA_DATA *pa_pkinit_kx)
+{
+ krb5_error_code ret;
+ EncryptedData ed;
+ krb5_keyblock ck, sk_verify;
+ krb5_crypto ck_crypto = NULL;
+ krb5_crypto rk_crypto = NULL;
+ size_t len;
+ krb5_data data;
+ krb5_data p1 = { sizeof("PKINIT") - 1, "PKINIT" };
+ krb5_data p2 = { sizeof("KEYEXCHANGE") - 1, "KEYEXCHANGE" };
+
+ heim_assert(ctx != NULL, "PKINIT context is non-NULL");
+ heim_assert(reply_key != NULL, "reply key is non-NULL");
+ heim_assert(session_key != NULL, "session key is non-NULL");
+
+ /* PA-PKINIT-KX is optional unless anonymous */
+ if (pa_pkinit_kx == NULL)
+ return ctx->anonymous ? KRB5_KDCREP_MODIFIED : 0;
+
+ memset(&ed, 0, sizeof(ed));
+ krb5_keyblock_zero(&ck);
+ krb5_keyblock_zero(&sk_verify);
+ krb5_data_zero(&data);
+
+ ret = decode_EncryptedData(pa_pkinit_kx->padata_value.data,
+ pa_pkinit_kx->padata_value.length,
+ &ed, &len);
+ if (ret)
+ goto out;
+
+ if (len != pa_pkinit_kx->padata_value.length) {
+ ret = KRB5_KDCREP_MODIFIED;
+ goto out;
+ }
+
+ ret = krb5_crypto_init(context, reply_key, 0, &rk_crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_decrypt_EncryptedData(context, rk_crypto,
+ KRB5_KU_PA_PKINIT_KX,
+ &ed, &data);
+ if (ret)
+ goto out;
+
+ ret = decode_EncryptionKey(data.data, data.length,
+ &ck, &len);
+ if (ret)
+ goto out;
+
+ ret = krb5_crypto_init(context, &ck, 0, &ck_crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_crypto_fx_cf2(context, ck_crypto, rk_crypto,
+ &p1, &p2, session_key->keytype,
+ &sk_verify);
+ if (ret)
+ goto out;
+
+ if (sk_verify.keytype != session_key->keytype ||
+ krb5_data_ct_cmp(&sk_verify.keyvalue, &session_key->keyvalue) != 0) {
+ ret = KRB5_KDCREP_MODIFIED;
+ goto out;
+ }
+
+out:
+ free_EncryptedData(&ed);
+ krb5_free_keyblock_contents(context, &ck);
+ krb5_free_keyblock_contents(context, &sk_verify);
+ if (ck_crypto)
+ krb5_crypto_destroy(context, ck_crypto);
+ if (rk_crypto)
+ krb5_crypto_destroy(context, rk_crypto);
+ krb5_data_free(&data);
+
+ return ret;
+}
+
static krb5_error_code
pk_rd_pa_reply_dh(krb5_context context,
const heim_octet_string *indata,
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment