Skip Menu |
 

Download (untitled) / with headers
text/plain 14.4KiB
From fcusack@ratbert.iconnet.net Wed Jan 6 17:27:07 1999
Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28]) by rt-11.MIT.EDU (8.7.5/8.7.3) with SMTP id RAA18130 for <bugs@RT-11.MIT.EDU>; Wed, 6 Jan 1999 17:27:06 -0500
Received: from ratbert.iconnet.net by MIT.EDU with SMTP
id AA18407; Wed, 6 Jan 99 17:27:07 EST
Received: (from fcusack@localhost)
by ratbert.iconnet.net (8.9.1/8.9.1) id RAA21759;
Wed, 6 Jan 1999 17:28:33 -0500 (EST)
Message-Id: <199901062228.RAA21759@ratbert.iconnet.net>
Date: Wed, 6 Jan 1999 17:28:33 -0500 (EST)
From: fcusack@iconnet.net
Reply-To: fcusack@iconnet.net
To: krb5-bugs@MIT.EDU
Cc: fcusack@iconnet.net
Subject: Principal impersonation when using SAM
X-Send-Pr-Version: 3.99

Show quoted text
>Number: 681
>Category: krb5-kdc
>Synopsis: It's possible to replay another principal's SAM data.
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: krb5-unassigned
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Wed Jan 06 17:28:01 EST 1999
>Last-Modified:
>Originator: Frank Cusack
>Organization:
Icon CMT Corp.
Show quoted text
>Release: krb5-current-19981119
>Environment:
Unix
System: SunOS ratbert 5.6 Generic_105181-09 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4

Show quoted text
>Description:
If authentication of 2 principal's requires the same SAM mechanism,
it's possible to use a known SAM reply from principal A to authenticate
as principal B. This is b/c the current SAM code doesn't do
enough checking on the returned SAM data.

The fix below is based on previous patches I submitted. Without
these patches (and this one), using SAM is significantly (critically)
weaker than not using it.
Show quoted text
>How-To-Repeat:
>Fix:
Index: include/k5-int.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/include/k5-int.h,v
retrieving revision 1.8
diff -u -r1.8 k5-int.h
--- k5-int.h 1998/12/02 23:16:14 1.8
+++ k5-int.h 1999/01/06 22:10:50
@@ -349,6 +349,7 @@
krb5_keyblock sam_key;
krb5_timestamp stime; /* for replay detection */
krb5_int32 susec;
+ krb5_principal client;
krb5_data msd; /* mechanism specific data */
} krb5_predicted_sam_response;

Index: kdc/preauth/pa_sam.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam.c,v
retrieving revision 1.2
diff -u -r1.2 pa_sam.c
--- pa_sam.c 1998/12/01 02:06:21 1.2
+++ pa_sam.c 1999/01/06 22:10:51
@@ -36,11 +36,6 @@
*/

/*
- * XXX Most (all?) of the sam types use the master database key to
- * encrypt the track-data. This is probably bad.
- */
-
-/*
* To define a new SAM type, place it in the sam_inst_map below,
* and take a look at the code for the other SAM types.
*
Index: kdc/preauth/pa_sam_cryptocard.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_cryptocard.c,v
retrieving revision 1.8
diff -u -r1.8 pa_sam_cryptocard.c
--- pa_sam_cryptocard.c 1998/12/02 23:16:14 1.8
+++ pa_sam_cryptocard.c 1999/01/06 22:10:51
@@ -242,14 +242,17 @@
} /* switch (mode) */
#endif /* KRBCONF_KDC_MODIFIES_KDB */

- /* Convert the SAD into a key. */
psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+ if (retval = krb5_copy_principal(context, request->client, &psr.client))
+ goto cleanup;
+
#ifdef USE_RCACHE
/* XXX Watch these types when time_t or krb5_timestamp changes. */
if (retval = krb5_us_timeofday(context, &psr.stime, &psr.susec))
goto cleanup;
#endif /* USE_RCACHE */

+ /* Convert the SAD into a key. */
if (retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
&predict_response, 0 /* salt */,
&psr.sam_key)) {
@@ -382,6 +385,7 @@
krb5_predicted_sam_response * psr = 0;
krb5_enc_sam_response_enc * esre = 0;
krb5_timestamp timenow;
+ char * princ_req = 0, *princ_psr = 0;

/* Sanity check */
if (sr->sam_type != PA_SAM_TYPE_CRYPTOCARD) {
@@ -419,6 +423,16 @@
goto cleanup;
}

+ if (retval = krb5_unparse_name(context, request->client, &princ_req))
+ goto cleanup;
+ if (retval = krb5_unparse_name(context, psr->client, &princ_psr))
+ goto cleanup;
+ if (strcmp(princ_req, princ_psr) != 0) {
+ com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+ "Principal mismatch in rb1 track-data!");
+ goto cleanup;
+ }
+
if (retval = krb5_timeofday(context, &timenow))
goto cleanup;

@@ -438,8 +452,8 @@
}

/* Now check the replay cache. */
- rep.client = "sam/rc"; /* Any fixed value will do, although this */
- rep.server = "sam/rc"; /* should not match any principal name. */
+ rep.client = princ_psr;
+ rep.server = "sam/rc"; /* Should not match any principal name. */
rep.ctime = psr->stime;
rep.cusec = psr->susec;
if (retval = krb5_rc_store(kdc_context, kdc_rcache, &rep)) {
@@ -508,6 +522,11 @@
krb5_free_predicted_sam_response(context, psr);
if (esre)
krb5_free_enc_sam_response_enc(context, esre);
+
+ if (princ_req)
+ krb5_xfree(princ_req);
+ if (princ_psr)
+ krb5_xfree(princ_psr);

if (!retval) {
setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
Index: kdc/preauth/pa_sam_digi_path.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_digi_path.c,v
retrieving revision 1.9
diff -u -r1.9 pa_sam_digi_path.c
--- pa_sam_digi_path.c 1998/12/02 23:16:15 1.9
+++ pa_sam_digi_path.c 1999/01/06 22:10:51
@@ -150,14 +150,18 @@
predict_response.data = response;
predict_response.length = 8;

- /* Convert the SAD into a key. */
psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+ if (retval = krb5_copy_principal(context, request->client, &psr.client))
+ goto cleanup;
+
+
#ifdef USE_RCACHE
/* XXX Watch these types when time_t or krb5_timestamp changes. */
if (retval = krb5_us_timeofday(context, &psr.stime, &psr.susec))
goto cleanup;
#endif /* USE_RCACHE */

+ /* Convert the SAD into a key. */
if (retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
&predict_response, 0 /* salt */,
&psr.sam_key)) {
@@ -281,6 +285,7 @@
krb5_predicted_sam_response * psr = 0;
krb5_enc_sam_response_enc * esre = 0;
krb5_timestamp timenow;
+ char * princ_req = 0, *princ_psr = 0;

/* Sanity check */
if (sr->sam_type != PA_SAM_TYPE_DIGI_PATH) {
@@ -318,6 +323,16 @@
goto cleanup;
}

+ if (retval = krb5_unparse_name(context, request->client, &princ_req))
+ goto cleanup;
+ if (retval = krb5_unparse_name(context, psr->client, &princ_psr))
+ goto cleanup;
+ if (strcmp(princ_req, princ_psr) != 0) {
+ com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+ "Principal mismatch in snk4 track-data!");
+ goto cleanup;
+ }
+
if (retval = krb5_timeofday(context, &timenow))
goto cleanup;

@@ -337,8 +352,8 @@
}

/* Now check the replay cache. */
- rep.client = "sam/rc"; /* Any fixed value will do, although this */
- rep.server = "sam/rc"; /* should not match any principal name. */
+ rep.client = princ_psr;
+ rep.server = "sam/rc"; /* Should not match any principal name. */
rep.ctime = psr->stime;
rep.cusec = psr->susec;
if (retval = krb5_rc_store(kdc_context, kdc_rcache, &rep)) {
@@ -392,6 +407,11 @@
krb5_free_predicted_sam_response(context, psr);
if (esre)
krb5_free_enc_sam_response_enc(context, esre);
+
+ if (princ_req)
+ krb5_xfree(princ_req);
+ if (princ_psr)
+ krb5_xfree(princ_psr);

if (!retval) {
setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
Index: kdc/preauth/pa_sam_grail.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_grail.c,v
retrieving revision 1.6
diff -u -r1.6 pa_sam_grail.c
--- pa_sam_grail.c 1998/12/02 23:16:15 1.6
+++ pa_sam_grail.c 1999/01/06 22:10:51
@@ -69,6 +69,9 @@
sc.sam_challenge.length = strlen(sc.sam_challenge.data);

psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+ if (retval = krb5_copy_principal(context, request->client, &psr.client))
+ goto cleanup;
+
#ifdef USE_RCACHE
/* XXX Watch these types when time_t or krb5_timestamp changes. */
if (retval = krb5_us_timeofday(context, &psr.stime, &psr.susec))
@@ -183,6 +186,7 @@
krb5_predicted_sam_response * psr = 0;
krb5_enc_sam_response_enc * esre = 0;
krb5_timestamp timenow;
+ char * princ_req = 0, *princ_psr = 0;

/* Sanity check */
if (sr->sam_type != PA_SAM_TYPE_GRAIL) {
@@ -220,6 +224,16 @@
goto cleanup;
}

+ if (retval = krb5_unparse_name(context, request->client, &princ_req))
+ goto cleanup;
+ if (retval = krb5_unparse_name(context, psr->client, &princ_psr))
+ goto cleanup;
+ if (strcmp(princ_req, princ_psr) != 0) {
+ com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+ "Principal mismatch in Grail track-data!");
+ goto cleanup;
+ }
+
if (retval = krb5_timeofday(context, &timenow))
goto cleanup;

@@ -239,8 +253,8 @@
}

/* Now check the replay cache. */
- rep.client = "sam/rc"; /* Any fixed value will do, although this */
- rep.server = "sam/rc"; /* should not match any principal name. */
+ rep.client = princ_psr;
+ rep.server = "sam/rc"; /* Should not match any principal name. */
rep.ctime = psr->stime;
rep.cusec = psr->susec;
if (retval = krb5_rc_store(kdc_context, kdc_rcache, &rep)) {
@@ -294,6 +308,11 @@
krb5_free_predicted_sam_response(context, psr);
if (esre)
krb5_free_enc_sam_response_enc(context, esre);
+
+ if (princ_req)
+ krb5_xfree(princ_req);
+ if (princ_psr)
+ krb5_xfree(princ_psr);

if (!retval) {
setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
Index: kdc/preauth/pa_sam_securid.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_securid.c,v
retrieving revision 1.7
diff -u -r1.7 pa_sam_securid.c
--- pa_sam_securid.c 1998/12/02 23:16:15 1.7
+++ pa_sam_securid.c 1999/01/06 22:10:53
@@ -142,6 +142,9 @@
g_sc.sam_response_prompt.length = strlen(g_sc.sam_response_prompt.data);

psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+ if (retval = krb5_copy_principal(context, request->client, &psr.client))
+ goto cleanup;
+
psr.msd.data = &g_sid_track_data;
psr.msd.length = sizeof(g_sid_track_data);
#ifdef USE_RCACHE
@@ -269,6 +272,7 @@
krb5_predicted_sam_response * psr = 0;
krb5_enc_sam_response_enc * esre = 0;
krb5_timestamp timenow;
+ char * princ_req = 0, *princ_psr = 0;

char * user = 0, cp;

@@ -378,6 +382,16 @@
goto cleanup;
}

+ if (retval = krb5_unparse_name(context, request->client, &princ_req))
+ goto cleanup;
+ if (retval = krb5_unparse_name(context, psr->client, &princ_psr))
+ goto cleanup;
+ if (strcmp(princ_req, princ_psr) != 0) {
+ com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+ "Principal mismatch in SecurID track-data!");
+ goto cleanup;
+ }
+
#ifdef USE_RCACHE
/* Probably not useful for SecurID, but what the hell. */
{
@@ -395,8 +409,8 @@
}

/* Now check the replay cache. */
- rep.client = "sam/rc"; /* Any fixed value will do, although this */
- rep.server = "sam/rc"; /* should not match any principal name. */
+ rep.client = princ_psr;
+ rep.server = "sam/rc"; /* Should not match any principal name. */
rep.ctime = psr->stime;
rep.cusec = psr->susec;
if (retval = krb5_rc_store(kdc_context, kdc_rcache, &rep)) {
@@ -551,6 +565,11 @@
krb5_free_enc_sam_response_enc(context, esre);
if (client_key.contents)
krb5_free_keyblock_contents(context, &client_key);
+
+ if (princ_req)
+ krb5_xfree(princ_req);
+ if (princ_psr)
+ krb5_xfree(princ_psr);

if (user)
krb5_xfree(user);
Index: lib/krb5/asn.1/asn1_k_decode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_decode.c,v
retrieving revision 1.8
diff -u -r1.8 asn1_k_decode.c
--- asn1_k_decode.c 1998/12/02 23:16:15 1.8
+++ asn1_k_decode.c 1999/01/06 22:10:55
@@ -815,7 +815,10 @@
get_field(val->sam_key,0,asn1_decode_encryption_key);
get_field(val->stime,1,asn1_decode_kerberos_time);
get_field(val->susec,2,asn1_decode_int32);
- opt_string(val->msd,3,asn1_decode_octetstring);
+ alloc_field(val->client,krb5_principal_data);
+ get_field(val->client,3,asn1_decode_realm);
+ get_field(val->client,4,asn1_decode_principal_name);
+ opt_string(val->msd,5,asn1_decode_octetstring);
end_structure();
val->magic = KV5M_PREDICTED_SAM_RESPONSE;
}
Index: lib/krb5/asn.1/asn1_k_encode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_encode.c,v
retrieving revision 1.8
diff -u -r1.8 asn1_k_encode.c
--- asn1_k_encode.c 1998/12/02 23:16:15 1.8
+++ asn1_k_encode.c 1999/01/06 22:10:55
@@ -949,7 +949,9 @@
{
asn1_setup();

- add_optstring(val->msd,3,asn1_encode_octetstring);
+ add_optstring(val->msd,5,asn1_encode_octetstring);
+ asn1_addfield(val->client,4,asn1_encode_principal_name);
+ asn1_addfield(val->client,3,asn1_encode_realm);
asn1_addfield(val->susec,2,asn1_encode_integer);
asn1_addfield(val->stime,1,asn1_encode_kerberos_time);
asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
Index: lib/krb5/error_tables/kv5m_err.et
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/error_tables/kv5m_err.et,v
retrieving revision 1.2
diff -u -r1.2 kv5m_err.et
--- kv5m_err.et 1998/11/25 06:50:50 1.2
+++ kv5m_err.et 1999/01/06 22:10:56
@@ -80,6 +80,5 @@
error_code KV5M_PASSWD_PHRASE_ELEMENT, "Bad magic number for passwd_phrase_element"
error_code KV5M_GSS_OID, "Bad magic number for GSSAPI OID"
error_code KV5M_GSS_QUEUE, "Bad magic number for GSSAPI QUEUE"
-error_code KV5M_RB1_TRACK_DATA, "Bad magic number for RB1_TRACK_DATA"

end
Index: lib/krb5/krb/kfree.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/krb/kfree.c,v
retrieving revision 1.4
diff -u -r1.4 kfree.c
--- kfree.c 1998/12/01 02:06:23 1.4
+++ kfree.c 1999/01/06 22:10:57
@@ -653,6 +653,8 @@
return;
if (psr->sam_key.contents)
krb5_free_keyblock_contents(ctx, &psr->sam_key);
+ if (psr->client)
+ krb5_free_principal(ctx, psr->client);
if (psr->msd.data)
krb5_free_data_contents(ctx, &psr->msd);
}
Show quoted text
>Audit-Trail:
>Unformatted: