diff options
author | Greg Hudson <ghudson@mit.edu> | 2014-12-09 12:37:44 -0500 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2015-03-02 17:31:56 -0500 |
commit | 21e4e653d8258d525f4b6ca87797d42a8bccc282 (patch) | |
tree | eebc94a96ee7c4dda5d4b09d8894b80ac4092202 | |
parent | ebd20d50039e5ef77384cf02f07ef0373ab8a8a6 (diff) | |
download | krb5-21e4e653d8258d525f4b6ca87797d42a8bccc282.zip krb5-21e4e653d8258d525f4b6ca87797d42a8bccc282.tar.gz krb5-21e4e653d8258d525f4b6ca87797d42a8bccc282.tar.bz2 |
Fix krb5_read_message handling [CVE-2014-5355]
In recvauth_common, do not use strcmp against the data fields of
krb5_data objects populated by krb5_read_message(), as there is no
guarantee that they are C strings. Instead, create an expected
krb5_data value and use data_eq().
In the sample user-to-user server application, check that the received
client principal name is null-terminated before using it with printf
and krb5_parse_name.
CVE-2014-5355:
In MIT krb5, when a server process uses the krb5_recvauth function, an
unauthenticated remote attacker can cause a NULL dereference by
sending a zero-byte version string, or a read beyond the end of
allocated storage by sending a non-null-terminated version string.
The example user-to-user server application (uuserver) is similarly
vulnerable to a zero-length or non-null-terminated principal name
string.
The krb5_recvauth function reads two version strings from the client
using krb5_read_message(), which produces a krb5_data structure
containing a length and a pointer to an octet sequence. krb5_recvauth
assumes that the data pointer is a valid C string and passes it to
strcmp() to verify the versions. If the client sends an empty octet
sequence, the data pointer will be NULL and strcmp() will dereference
a NULL pointer, causing the process to crash. If the client sends a
non-null-terminated octet sequence, strcmp() will read beyond the end
of the allocated storage, possibly causing the process to crash.
uuserver similarly uses krb5_read_message() to read a client principal
name, and then passes it to printf() and krb5_parse_name() without
verifying that it is a valid C string.
The krb5_recvauth function is used by kpropd and the Kerberized
versions of the BSD rlogin and rsh daemons. These daemons are usually
run out of inetd or in a mode which forks before processing incoming
connections, so a process crash will generally not result in a
complete denial of service.
Thanks to Tim Uglow for discovering this issue.
CVSSv2: AV:N/AC:L/Au:N/C:N/I:N/A:P/E:POC/RL:OF/RC:C
[tlyu@mit.edu: CVSS score]
(cherry picked from commit 102bb6ebf20f9174130c85c3b052ae104e5073ec)
ticket: 8050
version_fixed: 1.13.2
status: resolved
-rw-r--r-- | src/appl/user_user/server.c | 4 | ||||
-rw-r--r-- | src/lib/krb5/krb/recvauth.c | 9 |
2 files changed, 9 insertions, 4 deletions
diff --git a/src/appl/user_user/server.c b/src/appl/user_user/server.c index 09ea4e0..f2b5b61 100644 --- a/src/appl/user_user/server.c +++ b/src/appl/user_user/server.c @@ -111,8 +111,10 @@ int main(argc, argv) } #endif + /* principal name must be sent null-terminated. */ retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data); - if (retval) { + if (retval || pname_data.length == 0 || + pname_data.data[pname_data.length - 1] != '\0') { com_err ("uu-server", retval, "reading pname"); return 2; } diff --git a/src/lib/krb5/krb/recvauth.c b/src/lib/krb5/krb/recvauth.c index da836283..5adc6dd 100644 --- a/src/lib/krb5/krb/recvauth.c +++ b/src/lib/krb5/krb/recvauth.c @@ -59,6 +59,7 @@ recvauth_common(krb5_context context, krb5_rcache rcache = 0; krb5_octet response; krb5_data null_server; + krb5_data d; int need_error_free = 0; int local_rcache = 0, local_authcon = 0; @@ -77,7 +78,8 @@ recvauth_common(krb5_context context, */ if ((retval = krb5_read_message(context, fd, &inbuf))) return(retval); - if (strcmp(inbuf.data, sendauth_version)) { + d = make_data((char *)sendauth_version, strlen(sendauth_version) + 1); + if (!data_eq(inbuf, d)) { problem = KRB5_SENDAUTH_BADAUTHVERS; response = 1; } @@ -93,8 +95,9 @@ recvauth_common(krb5_context context, */ if ((retval = krb5_read_message(context, fd, &inbuf))) return(retval); - if (appl_version && strcmp(inbuf.data, appl_version)) { - if (!problem) { + if (appl_version != NULL && !problem) { + d = make_data(appl_version, strlen(appl_version) + 1); + if (!data_eq(inbuf, d)) { problem = KRB5_SENDAUTH_BADAPPLVERS; response = 2; } |