Fix weak random number hole
Obtained from: CERT
This commit is contained in:
parent
95238e0742
commit
08caf16158
60
eBones/README.PATCH
Normal file
60
eBones/README.PATCH
Normal file
@ -0,0 +1,60 @@
|
||||
READ THIS ENTIRE FILE BEFORE PROCEEDING!
|
||||
|
||||
This distribution contains a "diff" file suitable for using with the
|
||||
"patch" program to update your Kerberos (version 4) source tree. The
|
||||
gist of the patch is to replace calls to des_random_key() with calls
|
||||
to des_new_random_key().
|
||||
|
||||
The primary difference is that des_random_key() uses a seeding
|
||||
technique which is predictable and therefore
|
||||
vulnerable. des_new_random_key() uses a feedback mechanism based on
|
||||
the Data Encryption Standard (DES) and is seeded with a secret (and
|
||||
therefore unknown to an attacker) value. This value is the database
|
||||
master key, which is a convenient secret value.
|
||||
|
||||
This patch assumes that you have the new_rnd_key.c key module (which
|
||||
contains the definition and code for des_new_random_key()). It has
|
||||
been part of the standard Version 4 distribution since 1992 and is
|
||||
used in the admin server (our primary error at MIT was not upgrading
|
||||
all of Kerberos to use this newer generator. This patch finishes the
|
||||
job).
|
||||
|
||||
In addition to the patch file for the Kerberos distribution this
|
||||
distribution also contains a program for changing critical system keys
|
||||
(namely the "krbtgt" and "changepw.kerberos" keys). When you
|
||||
originally built your Kerberos database these keys were chosen at
|
||||
random, using the vulnerable version of the kerberos random number
|
||||
generator. Therefore it is possible for an attacker to mount an attack
|
||||
to guess these values. If an attacker can determine the key for the
|
||||
"krbtgt" ticket, they can construct tickets claiming to be any
|
||||
kerberos principal. Similarly if an attacker can obtain the
|
||||
"changepw.kerberos" key, they can change anyone's password.
|
||||
|
||||
The enclosed "fix_kdb_keys.c" (part of the patch file) program, which
|
||||
you run on the KDC server, will change these critical keys to new
|
||||
values using the newer random number generator. IMPORTANT: When you
|
||||
run fix_kdb_keys, all outstanding ticket granting tickets will
|
||||
immediately become invalid. This will be disruptive to your user
|
||||
community. We recommend that you either do this late at night or early
|
||||
in the morning before most users have logged in. Alternatively
|
||||
pre-announce a definitive time when you will run the program and
|
||||
inform your users that they will have to get new tickets at that time
|
||||
(using either "kinit" or simply by logging out and then in again).
|
||||
|
||||
NOTE: The only client program modified is "ksrvutil" which is used to
|
||||
generate new server keys. All other client/server programs are
|
||||
unaffected. End users do *not* need to obtain new versions of programs
|
||||
that use Kerberos. This is because most random number generation in
|
||||
the Kerberos system is done on the KDC system. By fixing kerberos.c
|
||||
you have repaired most of the damage.
|
||||
|
||||
To install this patch copy patch_krb to the toplevel of your Kerberos
|
||||
source tree. Then type:
|
||||
|
||||
patch -p0 <patch_krb
|
||||
|
||||
This will install changes to various kerberos modules to upgrade them
|
||||
to use des_new_random_key(). It also will install a new program,
|
||||
"fix_kdb_keys.c." After the patch is complete type "make world" at the
|
||||
toplevel of your Kerberos source tree. This will, among other things,
|
||||
build the fix_kdb_keys program.
|
@ -1,7 +1,7 @@
|
||||
# From: @(#)Makefile 5.1 (Berkeley) 6/25/90
|
||||
# $Id$
|
||||
# $Id: Makefile,v 1.1 1995/09/13 17:24:15 markm Exp $
|
||||
|
||||
SUBDIR= ext_srvtab kadmind kdb_destroy kdb_edit kdb_init kdb_util \
|
||||
kerberos kprop ksrvutil kstash make_keypair
|
||||
SUBDIR= ext_srvtab fix_kdb_keys kadmind kdb_destroy kdb_edit kdb_init \
|
||||
kdb_util kerberos kprop ksrvutil kstash make_keypair
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
10
eBones/usr.sbin/fix_kdb_keys/Makefile
Normal file
10
eBones/usr.sbin/fix_kdb_keys/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# From: @(#)Makefile 5.2 (Berkeley) 3/5/91
|
||||
# $Id: Makefile,v 1.7 1995/09/26 06:20:18 mark Exp $
|
||||
|
||||
PROG= fix_kdb_keys
|
||||
CFLAGS+=-DKERBEROS -DDEBUG
|
||||
DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
|
||||
LDADD= -L${KDBOBJDIR} -lkdb -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes
|
||||
NOMAN= YES
|
||||
|
||||
.include <bsd.prog.mk>
|
191
eBones/usr.sbin/fix_kdb_keys/fix_kdb_keys.c
Normal file
191
eBones/usr.sbin/fix_kdb_keys/fix_kdb_keys.c
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* $Source: /afs/net/project/krb4/src/admin/RCS/kdb_edit.c,v $
|
||||
* $Author: tytso $
|
||||
*
|
||||
* Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
|
||||
* of Technology.
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <mit-copyright.h>.
|
||||
*
|
||||
* This routine changes the Kerberos encryption keys for principals,
|
||||
* i.e., users or services.
|
||||
*/
|
||||
|
||||
/*
|
||||
* exit returns 0 ==> success -1 ==> error
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#ifdef NEED_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <des.h>
|
||||
#include <krb.h>
|
||||
#include <krb_db.h>
|
||||
/* MKEYFILE is now defined in kdc.h */
|
||||
#include <kdc.h>
|
||||
|
||||
char prog[32];
|
||||
char *progname = prog;
|
||||
int nflag = 0;
|
||||
int debug = 0;
|
||||
extern int krb_debug;
|
||||
|
||||
Principal principal_data;
|
||||
|
||||
static C_Block master_key;
|
||||
static Key_schedule master_key_schedule;
|
||||
static long master_key_version;
|
||||
|
||||
static char realm[REALM_SZ];
|
||||
|
||||
void fatal_error(), cleanup();
|
||||
void Usage();
|
||||
void change_principal();
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
|
||||
prog[sizeof prog - 1] = '\0'; /* make sure terminated */
|
||||
strncpy(prog, argv[0], sizeof prog - 1); /* salt away invoking
|
||||
* program */
|
||||
|
||||
/* Assume a long is four bytes */
|
||||
if (sizeof(long) != 4) {
|
||||
fprintf(stderr, "%s: size of long is %d.\n", prog, sizeof(long));
|
||||
exit(-1);
|
||||
}
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
for (i = 1; argv[0][i] != '\0'; i++) {
|
||||
switch (argv[0][i]) {
|
||||
|
||||
/* debug flag */
|
||||
case 'd':
|
||||
debug = 1;
|
||||
continue;
|
||||
|
||||
/* debug flag */
|
||||
case 'l':
|
||||
krb_debug |= 1;
|
||||
continue;
|
||||
|
||||
case 'n': /* read MKEYFILE for master key */
|
||||
nflag = 1;
|
||||
continue;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: illegal flag \"%c\"\n", progname, argv[0][i]);
|
||||
Usage(); /* Give message and die */
|
||||
}
|
||||
};
|
||||
|
||||
if (krb_get_lrealm(realm, 1)) {
|
||||
fprintf(stderr, "Couldn't get local realm information.\n");
|
||||
fatal_error();
|
||||
}
|
||||
|
||||
kerb_init();
|
||||
if (argc > 0) {
|
||||
if (kerb_db_set_name(*argv) != 0) {
|
||||
fprintf(stderr, "Could not open altername database name\n");
|
||||
fatal_error();
|
||||
}
|
||||
}
|
||||
|
||||
if (kdb_get_master_key ((nflag == 0),
|
||||
master_key, master_key_schedule) != 0) {
|
||||
fprintf (stderr, "Couldn't read master key.\n");
|
||||
fatal_error();
|
||||
}
|
||||
|
||||
if ((master_key_version = kdb_verify_master_key(master_key,
|
||||
master_key_schedule,
|
||||
stdout)) < 0)
|
||||
fatal_error();
|
||||
|
||||
des_init_random_number_generator(master_key);
|
||||
|
||||
change_principal("krbtgt", realm);
|
||||
change_principal("changepw", KRB_MASTER);
|
||||
|
||||
cleanup();
|
||||
|
||||
printf("\nKerberos database updated successfully. Note that all\n");
|
||||
printf("existing ticket-granting tickets have been invalidated.\n\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void change_principal(input_name, input_instance)
|
||||
char *input_name;
|
||||
char *input_instance;
|
||||
{
|
||||
int n, more;
|
||||
C_Block new_key;
|
||||
|
||||
n = kerb_get_principal(input_name, input_instance, &principal_data,
|
||||
1, &more);
|
||||
if (!n) {
|
||||
fprintf(stderr, "Can't find principal database for %s.%s.\n",
|
||||
input_name, input_instance);
|
||||
fatal_error();
|
||||
}
|
||||
if (more) {
|
||||
fprintf(stderr, "More than one entry for %s.%s.\n", input_name,
|
||||
input_instance);
|
||||
fatal_error();
|
||||
}
|
||||
|
||||
des_new_random_key(new_key);
|
||||
|
||||
/* seal it under the kerberos master key */
|
||||
kdb_encrypt_key (new_key, new_key,
|
||||
master_key, master_key_schedule,
|
||||
ENCRYPT);
|
||||
memcpy(&principal_data.key_low, new_key, 4);
|
||||
memcpy(&principal_data.key_high, ((long *) new_key) + 1, 4);
|
||||
memset(new_key, 0, sizeof(new_key));
|
||||
|
||||
principal_data.key_version++;
|
||||
|
||||
if (kerb_put_principal(&principal_data, 1)) {
|
||||
fprintf(stderr, "\nError updating Kerberos database");
|
||||
fatal_error();
|
||||
}
|
||||
|
||||
memset(&principal_data.key_low, 0, 4);
|
||||
memset(&principal_data.key_high, 0, 4);
|
||||
}
|
||||
|
||||
void fatal_error()
|
||||
{
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
|
||||
memset(master_key, 0, sizeof(master_key));
|
||||
memset(master_key_schedule, 0, sizeof(master_key_schedule));
|
||||
memset(&principal_data, 0, sizeof(principal_data));
|
||||
}
|
||||
|
||||
void Usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-n]\n", progname);
|
||||
exit(1);
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
* i.e., users or services.
|
||||
*
|
||||
* from: kdb_edit.c,v 4.2 90/01/09 16:05:09 raeburn Exp $
|
||||
* $Id: kdb_edit.c,v 1.5 1995/08/03 17:15:54 mark Exp $
|
||||
* $Id: kdb_edit.c,v 1.5 1995/09/07 21:37:17 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -18,7 +18,7 @@
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"$Id: kdb_edit.c,v 1.5 1995/08/03 17:15:54 mark Exp $";
|
||||
"$Id: kdb_edit.c,v 1.5 1995/09/07 21:37:17 markm Exp $";
|
||||
#endif lint
|
||||
#endif
|
||||
|
||||
@ -173,6 +173,8 @@ main(argc, argv)
|
||||
stdout)) < 0)
|
||||
exit (-1);
|
||||
|
||||
des_init_random_number_generator(master_key);
|
||||
|
||||
/* lookup the default values */
|
||||
n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
|
||||
&default_princ, 1, &more);
|
||||
@ -282,7 +284,7 @@ change_principal()
|
||||
bzero(new_key, sizeof(C_Block));
|
||||
new_key[0] = 127;
|
||||
#else
|
||||
random_key(new_key);
|
||||
des_new_random_key(new_key); /* yes, random */
|
||||
#endif
|
||||
bzero(pw_str, sizeof pw_str);
|
||||
}
|
||||
|
@ -7,13 +7,13 @@
|
||||
* already exists.
|
||||
*
|
||||
* from: kdb_init.c,v 4.0 89/01/24 21:50:45 jtkohl Exp $
|
||||
* $Id: kdb_init.c,v 1.4 1995/07/18 16:37:35 mark Exp $
|
||||
* $Id: kdb_init.c,v 1.4 1995/09/07 21:37:20 markm Exp $
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"$Id: kdb_init.c,v 1.4 1995/07/18 16:37:35 mark Exp $";
|
||||
"$Id: kdb_init.c,v 1.4 1995/09/07 21:37:20 markm Exp $";
|
||||
#endif lint
|
||||
#endif
|
||||
|
||||
@ -97,6 +97,7 @@ main(argc, argv)
|
||||
fprintf (stderr, "Couldn't read master key.\n");
|
||||
exit (-1);
|
||||
}
|
||||
des_init_random_number_generator(master_key);
|
||||
|
||||
if (
|
||||
add_principal(KERB_M_NAME, KERB_M_INST, MASTER_KEY) ||
|
||||
@ -140,7 +141,7 @@ add_principal(name, instance, aap_op)
|
||||
bzero(new_key, sizeof(C_Block));
|
||||
new_key[0] = 127;
|
||||
#else
|
||||
random_key(new_key);
|
||||
des_new_random_key(new_key);
|
||||
#endif
|
||||
kdb_encrypt_key (new_key, new_key, master_key, master_key_schedule,
|
||||
ENCRYPT);
|
||||
|
@ -5,13 +5,13 @@
|
||||
* <Copyright.MIT>.
|
||||
*
|
||||
* from: kerberos.c,v 4.19 89/11/01 17:18:07 qjb Exp $
|
||||
* $Id: kerberos.c,v 1.4 1995/09/07 21:37:27 markm Exp $
|
||||
* $Id: kerberos.c,v 1.5 1995/09/17 00:39:00 gibbs Exp $
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char rcsid[] =
|
||||
"$Id: kerberos.c,v 1.4 1995/09/07 21:37:27 markm Exp $";
|
||||
"$Id: kerberos.c,v 1.5 1995/09/17 00:39:00 gibbs Exp $";
|
||||
#endif lint
|
||||
#endif
|
||||
|
||||
@ -269,6 +269,7 @@ main(argc, argv)
|
||||
bzero (master_key_schedule, sizeof (master_key_schedule));
|
||||
exit (-1);
|
||||
}
|
||||
des_init_random_number_generator(master_key);
|
||||
|
||||
master_key_version = (u_char) kerror;
|
||||
|
||||
@ -434,7 +435,7 @@ kerberos(client, pkt)
|
||||
#ifdef NOENCRYPTION
|
||||
bzero(session_key, sizeof(C_Block));
|
||||
#else
|
||||
random_key(session_key);
|
||||
des_new_random_key(session_key);
|
||||
#endif
|
||||
/* unseal server's key from master key */
|
||||
bcopy(&s_name_data.key_low, key, 4);
|
||||
@ -565,7 +566,7 @@ kerberos(client, pkt)
|
||||
#ifdef NOENCRYPTION
|
||||
bzero(session_key, sizeof(C_Block));
|
||||
#else
|
||||
random_key(session_key);
|
||||
des_new_random_key(session_key);
|
||||
#endif
|
||||
|
||||
krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
|
||||
|
@ -12,7 +12,7 @@
|
||||
static char rcsid_ksrvutil_c[] =
|
||||
"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp ";
|
||||
static const char rcsid[] =
|
||||
"$Id: ksrvutil.c,v 1.1 1995/07/18 16:40:11 mark Exp $";
|
||||
"$Id: ksrvutil.c,v 1.5 1995/09/07 21:38:40 markm Exp $";
|
||||
#endif lint
|
||||
#endif
|
||||
|
||||
@ -523,16 +523,20 @@ get_svc_new_key(new_key, sname, sinst, srealm, keyfile)
|
||||
char *keyfile;
|
||||
{
|
||||
int status = KADM_SUCCESS;
|
||||
CREDENTIALS c;
|
||||
|
||||
if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME,
|
||||
KADM_SINST, 1, keyfile)) == KSUCCESS) &&
|
||||
((status = krb_get_cred(PWSERV_NAME, KADM_SINST, srealm, &c)) ==
|
||||
KSUCCESS) &&
|
||||
((status = kadm_init_link("changepw", KRB_MASTER, srealm)) ==
|
||||
KADM_SUCCESS)) {
|
||||
#ifdef NOENCRYPTION
|
||||
bzero((char *) new_key, sizeof(des_cblock));
|
||||
new_key[0] = (unsigned char) 1;
|
||||
#else /* NOENCRYPTION */
|
||||
des_random_key(new_key);
|
||||
des_init_random_number_generator(c.session);
|
||||
(void) des_new_random_key(new_key);
|
||||
#endif /* NOENCRYPTION */
|
||||
return(KADM_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user