-----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-----