CVE-2017-6594 (published 2017-08-28T19:29Z)

The transit path validation code in Heimdal before 7.3 might allow attackers to bypass the capath policy protection mechanism by leveraging failure to add the previous hop realm to the transit path of issued tickets.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-295
cwe_name: Improper Certificate Validation
description: The product does not validate, or incorrectly validates, a certificate.
extended_description: When a certificate is invalid or malicious, it might allow an attacker to spoof a trusted entity by interfering in the communication path between the host and client. The product might connect to a malicious host while believing it is a trusted host, or the product might be deceived into accepting spoofed data that appears to originate from a trusted host.
         

Fix information:
repo_url: https://github.com/heimdal/heimdal
commit_details: repo_url: https://github.com/heimdal/heimdal
author: Viktor Dukhovni
author_date: 2016-08-10 23:31:14+00:00
msg: Fix transit path validation CVE-2017-6594

Commit f469fc6 (2010-10-02) inadvertently caused the previous hop realm
to not be added to the transit path of issued tickets.  This may, in
some cases, enable bypass of capath policy in Heimdal versions 1.5
through 7.2.

Note, this may break sites that rely on the bug.  With the bug some
incomplete [capaths] worked, that should not have.  These may now break
authentication in some cross-realm configurations.
repository: repo_url: https://github.com/heimdal/heimdal
repo_name: heimdal/heimdal
description: Heimdal
repo_language: C
owner: heimdal
file_changes: filename: NEWS
change_type: ModificationType.MODIFY
diff: @@ -1,3 +1,17 @@
+Release Notes - Heimdal - Version Heimdal 7.3
+
+ Security
+
+ - Fix transit path validation.  Commit f469fc6 (2010-10-02) inadvertently
+   caused the previous hop realm to not be added to the transit path
+   of issued tickets.  This may, in some cases, enable bypass of capath
+   policy in Heimdal versions 1.5 through 7.2.
+
+   Note, this may break sites that rely on the bug.  With the bug some
+   incomplete [capaths] worked, that should not have.  These may now break
+   authentication in some cross-realm configurations.
+   (CVE-2017-6594)
+
 Release Notes - Heimdal - Version Heimdal 7.2
 
  Bug fixes

programming_language: Markdown
filename: krb5tgs.c
change_type: ModificationType.MODIFY
diff: @@ -655,8 +655,12 @@ fix_transited_encoding(krb5_context context,
 		  "Decoding transited encoding");
 	return ret;
     }
+
+    /*
+     * If the realm of the presented tgt is neither the client nor the server
+     * realm, it is a transit realm and must be added to transited set.
+     */
     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
-	/* not us, so add the previous realm to transited set */
 	if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
 	    ret = ERANGE;
 	    goto free_realms;
@@ -737,6 +741,7 @@ tgs_make_reply(krb5_context context,
 	       const char *server_name,
 	       hdb_entry_ex *client,
 	       krb5_principal client_principal,
+               const char *tgt_realm,
 	       hdb_entry_ex *krbtgt,
 	       krb5_enctype krbtgt_etype,
 	       krb5_principals spp,
@@ -798,7 +803,7 @@ tgs_make_reply(krb5_context context,
 				 &tgt->transited, &et,
 				 krb5_principal_get_realm(context, client_principal),
 				 krb5_principal_get_realm(context, server->entry.principal),
-				 krb5_principal_get_realm(context, krbtgt->entry.principal));
+				 tgt_realm);
     if(ret)
 	goto out;
 
@@ -1519,6 +1524,8 @@ tgs_build_reply(krb5_context context,
     krb5_keyblock sessionkey;
     krb5_kvno kvno;
     krb5_data rspac;
+    const char *tgt_realm = /* Realm of TGT issuer */
+        krb5_principal_get_realm(context, krbtgt->entry.principal);
     const char *our_realm = /* Realm of this KDC */
         krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
     char **capath = NULL;
@@ -2324,6 +2331,7 @@ server_lookup:
 			 spn,
 			 client,
 			 cp,
+                         tgt_realm,
 			 krbtgt_out,
 			 tkey_sign->key.keytype,
 			 spp,

programming_language: C
filename: check-kdc.in
change_type: ModificationType.MODIFY
diff: @@ -53,6 +53,7 @@ R4=TEST4.H5L.SE
 R5=SOME-REALM5.FR
 R6=SOME-REALM6.US
 R7=SOME-REALM7.UK
+R8=SOME-REALM8.UK
 
 H1=H1.$R
 H2=H2.$R
@@ -148,6 +149,12 @@ ${kadmin} \
     --realm-max-renewable-life=1month \
     ${R7} || exit 1
 
+${kadmin} \
+    init \
+    --realm-max-ticket-life=1day \
+    --realm-max-renewable-life=1month \
+    ${R8} || exit 1
+
 ${kadmin} \
     init \
     --realm-max-ticket-life=1day \
@@ -191,6 +198,7 @@ ${kadmin} add -p foo --use-defaults foo@${R4} || exit 1
 ${kadmin5} add -p foo --use-defaults foo@${R5} || exit 1
 ${kadmin} add -p foo --use-defaults foo@${R6} || exit 1
 ${kadmin} add -p foo --use-defaults foo@${R7} || exit 1
+${kadmin} add -p foo --use-defaults foo@${R8} || exit 1
 ${kadmin} add -p foo --use-defaults foo@${H1} || exit 1
 ${kadmin} add -p foo --use-defaults foo/host.${h1}@${H1} || exit 1
 ${kadmin} add -p foo --use-defaults foo@${H2} || exit 1
@@ -249,6 +257,9 @@ ${kadmin} add -p cross2 --use-defaults krbtgt/${R5}@${R6} || exit 1
 ${kadmin} add -p cross1 --use-defaults krbtgt/${R7}@${R6} || exit 1
 ${kadmin} add -p cross2 --use-defaults krbtgt/${R6}@${R7} || exit 1
 
+${kadmin} add -p cross1 --use-defaults krbtgt/${R8}@${R6} || exit 1
+${kadmin} add -p cross2 --use-defaults krbtgt/${R6}@${R8} || exit 1
+
 ${kadmin} add -p cross1 --use-defaults krbtgt/${H1}@${R} || exit 1
 ${kadmin} add -p cross2 --use-defaults krbtgt/${R}@${H1} || exit 1
 
@@ -284,6 +295,7 @@ ${kadmin} check ${R4} || exit 1
 ${kadmin5} check ${R5} || exit 1
 ${kadmin} check ${R6} || exit 1
 ${kadmin} check ${R7} || exit 1
+${kadmin} check ${R8} || exit 1
 ${kadmin} check ${H1} || exit 1
 ${kadmin} check ${H2} || exit 1
 ${kadmin} check ${H3} || exit 1
@@ -388,6 +400,8 @@ echo "Getting x-realm tickets with capaths for $R -> $R6"
 ${kgetcred} foo@${R6} || { ec=1 ; eval "${testfailed}"; }
 echo "Getting x-realm tickets with capaths for $R -> $R7"
 ${kgetcred} foo@${R7} || { ec=1 ; eval "${testfailed}"; }
+echo "Should not get x-realm tickets with capaths for $R -> $R8"
+${kgetcred} foo@${R8} && { ec=1 ; eval "${testfailed}"; }
 ${kdestroy}
 
 echo "Testing capaths logic (reverse order)"
@@ -418,10 +432,13 @@ ${kinit} --password-file=${objdir}/foopassword \
 
 echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $H1"
 ${kgetcred} --hostbased --canonicalize foo host.${h1} || { ec=1 ; eval "${testfailed}"; }
+fgrep "cross-realm ${H3} -> ${H1} via [${H2}, ${R}]" messages.log > /dev/null || { ec=1 ; eval "${testfailed}"; }
 echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $R"
 ${kgetcred} --hostbased --canonicalize foo host.${r} || { ec=1 ; eval "${testfailed}"; }
+fgrep "cross-realm ${H3} -> ${R} via [${H2}]" messages.log > /dev/null || { ec=1 ; eval "${testfailed}"; }
 echo "Getting x-realm tickets with hierarchical referrals for $H3 -> $H2"
 ${kgetcred} --hostbased --canonicalize foo host.${h2} || { ec=1 ; eval "${testfailed}"; }
+fgrep "cross-realm ${H3} -> ${H2}" messages.log > /dev/null || { ec=1 ; eval "${testfailed}"; }
 ${kdestroy}
 
 echo "Testing multi-hop [capaths] referral logic"

programming_language: Shell
filename: krb5.conf.in
change_type: ModificationType.MODIFY
diff: @@ -40,6 +40,9 @@
 	SOME-REALM7.UK = {
 		kdc = localhost:@port@
 	}
+	SOME-REALM8.UK = {
+		kdc = localhost:@port@
+	}
 	TEST-HTTP.H5L.SE = {
 		kdc = http/localhost:@port@
 	}
@@ -147,6 +150,7 @@
 		SOME-REALM6.US = SOME-REALM5.FR
 		SOME-REALM7.UK = SOME-REALM6.US
 		SOME-REALM7.UK = SOME-REALM5.FR
+		SOME-REALM8.UK = SOME-REALM6.US
 	}
         H4.H2.TEST.H5L.SE = {
                 H1.TEST.H5L.SE = H3.H2.TEST.H5L.SE

programming_language: Lua