-----BEGIN PGP SIGNED MESSAGE-----
Description of kadmind4 Attack Signature
These notes are probably only applicable to code significantly similar
to the MIT kadmind4 implementation (both the krb5 compatibility daemon
and the original krb4 implementation), though Heimdal's code paths
seem like they may result in the same effects.
Note: It is believed that at least one attacker is reasonably
competent at cleaning up traces of intrusion. A successful attack may
not result in *any* discernible evidence on the compromised host
itself.
An attempted attack on kadmind4 can result in several types of log
messages. Most of these are logged by kadm_ser_in() as it is
performing an error return. Since in the normal operation of
kadmind4, kadm_ser_in() is called within a child process, any abnormal
process termination will be noticed and logged by the parent. For
example:
Oct 23 00:18:29 kadmind4[15508]: [ID 895325 local6.error] child 15514: termsig 11, retcode 0
Attack attempts that do not result in abnormal child termination may
cause the logging of other errors. The exact form of these log
messages may vary depending on the particular kadmind4 implementation;
note in particular that the kadmind4 included with MIT krb5 does not
initialize the "krb" error table, so these errors will appear as
"unknown error krb ###".
Error conditions encountered in kadm_ser_in() result in an error
packet being generated (but not sent), and an error code being
returned. The caller of kadm_ser_in(), which is process_client() in
admin_server.c, is responsible for logging the error code returned
from kadm_ser_in(), as well as transmitting the error packet to the
client. An attack attempt that results in a successful return from
kadm_ser_in(), i.e. one that probably does not result in the execution
of attacker-chosen code or that does not crash the child process, will
cause kadmind4 to both send an error packet to the client and log an
error message.
One possible way to distinguish between attempted attacks and
legitimate requests encountering error conditions is to time-correlate
requests for tickets for the "changepw.kerberos" service with the
error messages in question. This of course does not help in cases
where the attacker happens to request "changepw.kerberos" tickets
prior to making an attack. Note that some skew must be accommodated
when doing this time correlation, since a real user may delay somewhat
between typing an old password and entering the new one twice.
An actual attack signature might produce a few child process crashes
and/or a few error logs, followed by the actual successful exploit,
which may not result in any error logs at all. This progression may
occur as the attacker adjusts parameters of the attack for the stack
pointer and stack layout of a particular instance of kadmind4.
If the attacker tunes the initial attack to avoid a segmentation fault
inside memcpy(), there may not be any crashes preceding the error
logs, especially on architectures such as SPARC that use register
windows. The reason would be that if the return address of
kadm_ser_in() is in a window that has not been written to the stack
frame due to a window spill trap by the call to memcpy(), then the
overflow of the on-stack buffer would not be able to modify the return
address of kadm_ser_in().
The following is a list of likely errors returned from kadm_ser_in()
during the course of an attempted attack. It is not an exhaustive
list. The errors are listed by their krb.h CPP macros, and also
include text that may be logged by kadmind4. Note that some of these
might be produced by legitimate requests under certain conditions, and
that the actual text may vary from one implementation to another.
RD_AP_UNDEC
"unknown error krb 31" or
"Kerberos error: Can't decode authenticator"
* decomp_tkt() fails -- note: this hasn't been seen in any
logs we've looked at.
RD_AP_VERSION
"unknown error krb 39" or
"Kerberos protocol version mismatch"
* example:
Oct 22 16:05:08 kadmind4[13767]: [ID 692406 local6.error] processing request: Unknown code krb 39
* logged if rd_req() gets wrong first byte -- this is quite
likely in an exploit attempt unless the attacker forces the
correct first byte
RD_AP_MSG_TYPE
"unknown error krb 40" or
"Kerberos error: invalid msg type"
* rd_req() -- note: this hasn't been seen in any logs we've
looked at.
RD_AP_MODIFIED
"unknown error krb 41"
"Kerberos error: message stream modified"
* example:
Oct 22 15:56:35 kadmind4[13725]: [ID 692406 local6.error] processing request: Unknown code krb 41
* rd_req()
* len <= 0 -- unlikely; an attack that causes there to
be a negative value of authent.length will likely
cause mempcy() to fault, and is thus likely to fail
while logging a segmentation fault similar (at least
on a system where the process memory limit is
small).
* realm too long -- rather likely in an exploit
attempt, but assumes that the attacker is attempting
to make something that looks like a krb4 ticket,
which isn't strictly necessary in order to exploit
this vulnerability.
* many other places in this function can produce this
error.
* rd_priv()
Note that here, the likely cause is a user behind a
NAT making a legitimate request to kadmind4.
ACKNOWLEDGMENTS
===============
Thanks to Bill Sommerfeld for enlightening discussion about SPARC
register window details.
Thanks to Love Hornquist-Astrand for providing some useful background
information.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (SunOS)
iQCVAwUBPbnaoabDgE/zdoE9AQGmJAP/cHFy1rlXBleHnmNabix3n/ZKWaSEEFVa
KpvLiRCMJL7shUTQ8VA3efDIuadPPHhS+3TDXkvS1hMC3Ok2Bb3IGMUb5GL5KvKN
/79AWIWx+z7OwLSb0Z1jqy42ImT49z4bf4DIpzQixQyV/LWLfTPr6MpCnxRbziOE
a0gmkbk2txM=
=h+UA
-----END PGP SIGNATURE-----