CVE-2014-9423: Exposure of Sensitive Information to an Unauthorized Actor (CWE-200)
value: The svcauth_gss_accept_sec_context function in lib/rpc/svc_auth_gss.c in MIT Kerberos 5 (aka krb5) 1.11.x through 1.11.5, 1.12.x through 1.12.2, and 1.13.x before 1.13.1 transmits uninitialized interposer data to clients, which allows remote attackers to obtain sensitive information from process heap memory by sniffing the network for data in a handle field.
CWE description: The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Published: 2015-02-19T11:59Z
Repository: https://github.com/krb5/krb5
Language: C
Files changed: src/lib/gssapi/mechglue/mglueP.h, src/lib/rpc/svc_auth_gss.c
Commit date: 2015-02-04 14:26:15 -0500
Commit message: Fix gssrpc data leakage [CVE-2014-9423]

[MITKRB5-SA-2015-001] In svcauth_gss_accept_sec_context(), do not copy
bytes from the union context into the handle field we send to the
client.  We do not use this handle field, so just supply a fixed
string of "xxxx".

In gss_union_ctx_id_struct, remove the unused "interposer" field which
was causing part of the union context to remain uninitialized.

ticket: 8058 (new)
target_version: 1.13.1
tags: pullup

Diff: diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index e56b9c1a58f..2b5145e079f 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -23,11 +23,10 @@ do {								\
 /*
  * Array of context IDs typed by mechanism OID
  */
 typedef struct gss_union_ctx_id_struct {
 	struct gss_union_ctx_id_struct *loopback;
-	struct gss_union_ctx_id_struct *interposer;
 	gss_OID			mech_type;
 	gss_ctx_id_t		internal_ctx_id;
 } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
 
 /*
diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c
index 09a353412fe..b81c4a34963 100644
--- a/src/lib/rpc/svc_auth_gss.c
+++ b/src/lib/rpc/svc_auth_gss.c
@@ -63,20 +63,10 @@ extern const gss_OID_desc * const gss_mech_spkm3;
 
 #endif /* SPKM */
 
 extern SVCAUTH svc_auth_none;
 
-/*
- * from mit-krb5-1.2.1 mechglue/mglueP.h:
- * Array of context IDs typed by mechanism OID
- */
-typedef struct gss_union_ctx_id_t {
-  gss_OID     mech_type;
-  gss_ctx_id_t    internal_ctx_id;
-} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
-
-
 static auth_gssapi_log_badauth_func log_badauth = NULL;
 static caddr_t log_badauth_data = NULL;
 static auth_gssapi_log_badauth2_func log_badauth2 = NULL;
 static caddr_t log_badauth2_data = NULL;
 static auth_gssapi_log_badverf_func log_badverf = NULL;
@@ -237,20 +227,12 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst,
 	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
 		badauth(gr->gr_major, gr->gr_minor, rqst->rq_xprt);
 		gd->ctx = GSS_C_NO_CONTEXT;
 		goto errout;
 	}
-	/*
-	 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
-	 * one to the mechanism oid, one to the internal_ctx_id
-	 */
-	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
-		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
-		goto errout;
-	}
-	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
-	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);
+	gr->gr_ctx.value = "xxxx";
+	gr->gr_ctx.length = 4;
 
 	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
 	gr->gr_win = sizeof(gd->seqmask) * 8;
 
 	/* Save client info. */
@@ -518,22 +500,19 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
 		if (!svcauth_gss_accept_sec_context(rqst, &gr))
 			ret_freegc (AUTH_REJECTEDCRED);
 
 		if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) {
 			gss_release_buffer(&min_stat, &gr.gr_token);
-			mem_free(gr.gr_ctx.value,
-				 sizeof(gss_union_ctx_id_desc));
 			ret_freegc (AUTH_FAILED);
 		}
 		*no_dispatch = TRUE;
 
 		call_stat = svc_sendreply(rqst->rq_xprt, xdr_rpc_gss_init_res,
 					  (caddr_t)&gr);
 
 		gss_release_buffer(&min_stat, &gr.gr_token);
 		gss_release_buffer(&min_stat, &gd->checksum);
-		mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc));
 		if (!call_stat)
 			ret_freegc (AUTH_FAILED);
 
 		if (gr.gr_major == GSS_S_COMPLETE)
 			gd->established = TRUE;

Vulnerable code: 	struct gss_union_ctx_id_struct *interposer;
/*
 * from mit-krb5-1.2.1 mechglue/mglueP.h:
 * Array of context IDs typed by mechanism OID
 */
typedef struct gss_union_ctx_id_t {
  gss_OID     mech_type;
  gss_ctx_id_t    internal_ctx_id;
} gss_union_ctx_id_desc, *gss_union_ctx_id_t;


	/*
	 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
	 * one to the mechanism oid, one to the internal_ctx_id
	 */
	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
		goto errout;
	}
	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);
			mem_free(gr.gr_ctx.value,
				 sizeof(gss_union_ctx_id_desc));
		mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc));
Fixed code: 	gr->gr_ctx.value = "xxxx";
	gr->gr_ctx.length = 4;