Bugtraq mailing list archives

Re: Exploit of rpc.cmsd


From: appro () FY CHALMERS SE (Andy Polyakov)
Date: Sat, 10 Jul 1999 17:01:09 +0200


Hi, everybody!

The calendar manager (rpc.cmsd) on Solaris 2.5 and 2.5.1 is vulnerable
to a buffer overflow
attack...
Can you confirm that compromised system(s) were equipped with CDE? Or in
other words was it /usr/dt/bin/rpc.cmsd that was assigned to do the job
in /etc/inetd.conf?
Further, it appears that even patched versions may be
vulnerable.
Could you be more specific here and tell exactly which patches are you
talking about?
I've got reply from Bob that it's whatever patches included into
corresponding "Recommended Patch Cluster" he's talking about and it's
/usr/openwin/bin/rpc.cmsd he had engaged. I still want to point out here
that CDE patches are not included into those clusters and if you have
CDE installed you have to do better than just ./install_cluster. Well,
this of course helps only *if* the problem in question was brought to
Sun's attention earlier *and* was actually fixed.
Also, rpc.cmsd under
Solaris 2.6 could also be problematic.
In mean time I made some observations...

Note that both /usr/openwin/bin/rpc.cmsd and /usr/dt/bin/rcp.cmsd drop
their root privileges all the way down to euid=ruid=suid=1 under
2.5[.1]. It's definitely not the case under 2.6 and 7 where rpc.cmsd
runs as euid=1,ruid=suid=0 and can regain root priveleges at any time.
What does it mean? If 2.5[.1] does exhibit buffer overflow, then root
exploit has to be two-stage. While in 2.6 and 7 case it might be a
classic one... Of course *if* they do exhibit buffer overflow... Well,
the very least we know is that Sun considers some buffer overflows fixed
in 2.6 by 105566-07. Shall we have a look? Let's 'cm_lookup -c
blah-blah () 2 6 host' and simultaneously 'truss -p <rpc.cmsd's pid> on
2.6.host:

...
statvfs("/var/spool/calendar/callog.blah-blah", 0xEFFFF88C) Err#2 ENOENT
open("/usr/spool/calendar/callog.blah-blah", O_RDONLY) Err#2 ENOENT
...

Aha! I can choose whatever name I like! Well, doesn't necessarily mean a
shit... But statvfs is a rare system call so let's 'dis
/usr/dt/bin/rpc.cmsd' and look for calls to statvfs... There're only
two! Fist call to statvfs in FCS version looks like following:

        ...
        1fb80:  40 01 1d 02        call         malloc
        1fb84:  90 10 21 01        mov          257, %o0
        1fb88:  b8 10 00 08        mov          %o0, %i4
        ...
        1fbc4:  90 10 00 1c        mov          %i4, %o0
        1fbc8:  40 01 1d 0e        call         sprintf
        1fbcc:  94 10 00 10        mov          %l0, %o2
        1fbd0:  90 07 bf 24        add          %fp, -220, %o0
        1fbd4:  40 01 1d 38        call         strcat
        1fbd8:  92 10 00 1c        mov          %i4, %o1
        1fbdc:  90 07 bf 24        add          %fp, -220, %o0
        1fbe0:  40 01 1d 38        call         statvfs
        1fbe4:  92 07 bf 64        add          %fp, -156, %o1
        ...

Doesn't look good, huh? Indeed! %i4 points at 257 large buffer allocated
with malloc. Then they do sprintf to it and then strcat it to %fp-220
resulting in %fp-220 pointing at "/var/spool/calendar/callog.blah-blah".
What makes me worried is that nor sprintf or strcat performs boundary
checks. Well, one can still instruct sprintf in the format line... BUT!
The buffer %i4 points at is 257 bytes large. And how much do we have
left in %fp-220? What do they smash with stack overruns? Something
between %fp and %fp-96, right? Secondly "/var/spool/calendar/callog." is
a 27 char long constant. So that we can't have more than 220-96-27=97
bytes left in %fp-220 which is way less than 257 %i4 points to...

But let's have a look at rpc.cmsd coming with 105566-07:

        ...
        1fbf4:  40 01 1d c4        call         malloc
        1fbf8:  90 10 21 01        mov          257, %o0
        1fbfc:  b8 10 00 08        mov          %o0, %i4
        ...
        1fc3c:  90 10 00 1c        mov          %i4, %o0
        1fc40:  92 10 21 01        mov          257, %o1
        1fc44:  40 01 1d 98        call         snprintf
        1fc48:  96 10 00 10        mov          %l0, %o3
        1fc4c:  40 01 1d 8a        call         strlen
        1fc50:  90 07 bf 24        add          %fp, -220, %o0
        1fc54:  b0 10 00 08        mov          %o0, %i0
        1fc58:  40 01 1d 87        call         strlen
        1fc5c:  90 10 00 1c        mov          %i4, %o0
        1fc60:  90 06 00 08        add          %i0, %o0, %o0
        1fc64:  80 a2 20 3f        cmp          %o0, 63
        1fc68:  a2 10 20 00        clr          %l1
        1fc6c:  ba 10 20 00        clr          %i5
        1fc70:  08 80 00 04        bleu         0x1fc80
        1fc74:  90 07 bf 24        add          %fp, -220, %o0
        ...
        1fc80:  40 01 1d ec        call         strcat
        1fc84:  92 10 00 1c        mov          %i4, %o1
        1fc88:  90 07 bf 24        add          %fp, -220, %o0
        1fc8c:  40 01 1d ec        call         statvfs
        1fc90:  92 07 bf 64        add          %fp, -156, %o1
        ...

Wow! Much, much better! First they make sure %i4 is intact with snprintf
and secondly they make sure that strlen(%fp-220)+strlen(%i4) is no
larger than 63 before calling strcat. It definitely looks like a stack
overrun being actually fixed here, doesn't it?

But we still don't know if this is the statvfs corresponding to the
truss log shown above and FCS version doesn't necessarily have to
exploitable. So let's have a look at the second statvfs call. That piece
of code look exactly the same in *both* FCS and 105566-07 versions:

        ...
        39b50:  40 00 b7 01        call         umask
        39b54:  90 10 20 02        mov          2, %o0
        39b58:  7f ff fc dd        call         init_dir
        39b5c:  01 00 00 00        nop
        39b60:  11 00 01 57        sethi        %hi(0x55c00), %o0
        39b64:  92 02 20 40        add          %o0, 0x40, %o1
        39b68:  11 00 01 57        sethi        %hi(0x55c00), %o0
        39b6c:  94 02 20 44        add          %o0, 0x44, %o2
        39b70:  40 00 b6 03        call         sprintf
        39b74:  90 07 be e4        add          %fp, -284, %o0
        39b78:  90 07 be e4        add          %fp, -284, %o0
        39b7c:  40 00 b6 30        call         statvfs
        39b80:  92 07 bf 24        add          %fp, -220, %o1
        ...

Two things. They again sprintf to a (%fp-220)-(%fp-284)=64 bytes large
buffer which is dangerous. Yes, I know it doesn't necessarily means it's
exploitable. BUT! On the other hand it's definitely not the code
corresponding to the truss log, because I haven't seen no umask before
statvfs.

Yeah! Do apply 105566-07 a.s.a.p., it does fix something! But what about
2.5[.1] and 7? Well, 2.5[.1] rpc.cmsd (i.e., both /usr/dt and
/usr/openwin versions) unfortunately do not make any distinguishable
system calls in reply to 'cm_lookup -c system calls in reply to 'cm_lookup -c blah-blah@2.5[.1].host' and I
can't easily locate relevant code as analyzing the whole disassembler
list doesn't really turn me on. As for 7, I leave it for your
homework...

Andy.


Current thread: