Vulnerability Development mailing list archives

Unsafe Signal Handling unix_chkpwd?


From: Charles Stevenson <core () ezlink com>
Date: Thu, 31 May 2001 19:57:16 -0600

Michal Zalewski wrote:

Hi, great paper.  I just started hammering at all the standard suid binaries
and at the moment I'm trying to determine if unix_chkpwd is exploitable:

static void _log_err(int err, const char *format,...)
{
 va_list args;

 va_start(args, format);
 openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTH);
 vsyslog(err, format, args);
 va_end(args);
 closelog();
}

There aren't any calls to free() although exit() was not in your list of
async-signal safe functions so I will make a grand assumption that possibly
one of the routines in exit()s cleanup could be exploited. Or possibly
closelog() or va_end().

static void su_sighandler(int sig)
{
 if (sig > 0) {
  _log_err(LOG_NOTICE, "caught signal %d.", sig);
  exit(sig);
 }
}

As you can see the signal handler performs syslog calls.  The first thing
unix_chkpwd does in main() is setup the signal handlers for various signals:

setup_signals();

If the program is run from a TTY device the program happily logs and then
sleep()s for 10 seconds. I was thinking at first that a signals could be
sent to cause the signal handler to be re-entered but there's not really any
way of getting this to overflow as far as I can know.

I actually was able to get around this by sending a SIGABRT which
immediately terminates the program.  So it may still be possible to brute
force unix_chkpwd by sending in a password and then a SIGABRT until you get
it :-).  It's possible to get input to the program by piping the output of
another program to it:

 echo "core is bored" | unix_chkpwd & sleep 1; killall -ILL unix_chkpwd;
sleep 1; killall -TRAP unix_chkpwd

This doesn't quite work... produces a log entry like this:

May 31 19:04:31 localhost unix_chkpwd[1073]: no password supplied

In any case... back to the nice sleep(10) line...

unix_chkpwd & sleep 1; killall -ILL unix_chkpwd; sleep 1; killall -TRAP
unix_chkpwd
[1] 1254
This binary is not designed for running in this way
-- the system administrator has been informed
[1]  + exit 4     unix_chkpwd
unix_chkpwd: no process killed

It exits too quickly with the sleep.

May 31 19:25:03 localhost unix_chkpwd[1254]: inappropriate use of Unix
helper binary [UID=1000]
May 31 19:25:04 localhost unix_chkpwd[1254]: caught signal 4.

So I tried without the sleep:

[-(core@euclid:~)> unix_chkpwd & sleep 1; killall -TRAP unix_chkpwd; killall
-SEGV unix_chkpwd
[1] 1266
This binary is not designed for running in this way
-- the system administrator has been informed
[-(core@euclid:~)>
[-(01-05-31-19:28:22)-]<pts/4>
[1]  + exit 11    unix_chkpwd

May 31 19:29:53 localhost unix_chkpwd[1288]: inappropriate use of Unix
helper binary [UID=1000]
May 31 19:29:54 localhost unix_chkpwd[1288]: caught signal 11.

It does exit with SIGSEGV so I assume the signal handler is getting
re-entered. Am I wrong?

Running Debian GNU/Linux unstable arch/ppc:
ii  libpam-modules 0.72-24        Pluggable Authentication Modules for PAM

Any suggestions? Is this impossible to exploit? If you get something going
I'd appreciate a copy ;-)

Best Regards,
Charles Stevenson

P.S. This was written in tired haste... forgive the jumps in my train of
thought :-)

RAZOR advisory: Unsafe Signal Handling in Sendmail

   Issue Date: May 28, 2001
   Contact: Michal Zalewski <lcamtuf () razor bindview com>

Topic:

   Sendmail signal handlers used for dealing with specific signals are
   vulnerable to numerous race conditions.

Affected Systems:

   Any systems running sendmail (tested on sendmail 8.11.0, 8.12.0-Beta5)

Details:

   Sendmail signal handlers used for dealing with specific signals
   (SIGINT, SIGTERM, etc) are vulnerable to numerous race conditions,
   including handler re-entry, interrupting non-reentrant libc functions
   and entering them again from the handler (see "References" for more
   details on this family of vulnerabilities). This set of
   vulnerabilities exist because of unsafe library function calls from
   signal handlers (malloc, free, syslog, operations on global buffers,
   etc).

   As sendmail is setuid root and can be invoked by user, and - moreover
   - keeps running with root privileges almost all the time, there is no
   problem with delivering signals at a specific moment.

   It is worth mentioning that not only sendmail is suspectible to have
   this kind of problems. Moreover, in some situations, unsafe signal
   handlers can be even exploited remotely, by delivering SIGURG over TCP
   stream (OOB message). Whenever SIGURG is handled in remote daemons in
   verbose way using unsafe functions, this is an exploitable condition.
   Note, sendmail is not vulnerable to this.

Impact:

   One of the attack paths we can see is delivering SIGTERM while
   sendmail is working in 'verbose debugging' mode (-d switch). SIGTERM
   handler works less or more this way:

     - ...
     - syslog(...) call with user-dependent information
     - ...
     - fclose(...)
     - free(...)
     - free(...)
     - ...
     - exit(...)

   This is important that syslog() function effectively calls malloc()
   code to allocate a temporary buffer. As exactly the same handler is
   used for SIGINT, and there is no re-entry protection in this handler,
   we can reach appropriate (usually the second) free() call, and deliver
   SIGTERM. Then, already free()d memory will be overwritten with
   user-dependent data from syslog() buffer, as new memory chunk would
   fit in the place of free()d buffers. Then, duplicate free() attempt on
   the memory region containing user-dependent data will be performed,
   which would lead to program execution path compromise. This is a
   difficult race, but can be attempted numerous times.

   Note that avoiding re-entry into signal handler is not the only thing
   that has to be done. Other possibilities include e.g. re-entering
   functions like malloc() - in this case, signal has to be delivered
   only once, in the middle of malloc() call. That would lead to heap
   corruption. Any functions that are not reentrant should be protected
   in a special way or not used at all in signal handlers.

Vendor response / fix info:

   From sendmail-security () sendmail org:

   We agree with Michal Zalewski's comments regarding the possibility of
   heap corruption due to signal delivery. We do not believe the heap
   corruption to be easily exploitable due to the complexity involved
   with timing and the little control the user has over the contents of
   memory in the signal handler. This is different than buffer overflows
   attacks which occur on the stack and allow users to insert specific
   instructions at a known location. At the present time, there is no
   proof that this is exploitable as there are no known exploits.

   However, the corruption could crash the process and we have taken
   measures to reduce this possibility in 8.11.4. We have eliminated the
   ability to reenter a signal handler making the attack discussed above
   impossible. Additionally, sendmail 8.12 will no longer require a
   set-user-id root binary.

   Note that this attack can only be used by a process started by the
   user and therefore can not be used as a denial of service attack and
   also is not remotely exploitable. The information regarding remote
   attacks and SIGURG does not apply to sendmail as SMTP does not use out
   of band messages.

References:

   For more information on signal delivery race conditions, please
   refer to RAZOR whitepaper at:

     http://razor.bindview.com/publish/papers/signals.txt


Current thread: