[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: another rsh fix



On Mon, Aug 16, 1999 at 02:52:36PM +1000, Brian A May wrote:
> Now that is understandable that there still may be problems with rshx.
> What I find incredibly hard to believe, is that the same command
> works fine on Ultrix!!!!!

The problem occurs when rshd.c calls abort(), common.c line 68.
At a quick guess, I would say the problem is buffer overflow.
The size of the incoming packet is too big and cannot be read, so
rshd.c aborts. Can this abort() be replaced with a descriptive error
message?

Now, my guess is that is just a symptom of the *real* problem. The real
problem, being, why does rsh on OSF/1 permit a packet to be sent that
is too large???

Can anyone tell me what the difference is between len and outer_len?
Why is outer_len bigger? I suspect that this is the key to the
whole problem. len is fine, outer_len is too big by 32 bytes. It looks
like rsh doesn't allow for this expansion by 32 bytes, whatever might
be doing it.

snoopy# gdb /usr/local/lib/heimdal/libexec/rshd
GNU gdb 4.17.m68k.objc.threads.hwwp.fpu.gnat
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i486-pc-linux-gnu"...
(gdb) l
797         else
798             syslog (LOG_ERR, "Usage: %s [-ikxlvPL] [-p port]", __progname);
799         exit (ret);
800     }
801
802
803     int
804     main(int argc, char **argv)
805     {
806         int optind = 0;
(gdb) set args  -i -k -p8000
(gdb) r
Starting program: /usr/local/lib/heimdal/libexec/rshd -i -k -p8000

Program exited normally.
(gdb) r
Starting program: /usr/local/lib/heimdal/libexec/rshd -i -k -p8000

Program received signal SIGABRT, Aborted.
0x400c7601 in kill ()
(gdb) bt
#0  0x400c7601 in kill ()
#1  0x400c742f in gsignal ()
#2  0x400c864f in abort ()
#3  0x804aef1 in do_read (fd=0, buf=0xbfff932c, sz=16384)
    at ../../../appl/rsh/common.c:68
#4  0x804a2d2 in loop (from0=0, to0=9, to1=1, from1=11, to2=2, from2=14)
    at ../../../appl/rsh/rshd.c:417
#5  0x804a5a7 in setup_copier () at ../../../appl/rsh/rshd.c:504
#6  0x804ac11 in doit (do_kerberos=1, check_rhosts=0)
    at ../../../appl/rsh/rshd.c:721
#7  0x804ae59 in main (argc=4, argv=0xbffffd44) at ../../../appl/rsh/rshd.c:856
(gdb) up
#1  0x400c742f in gsignal ()
(gdb) up
#2  0x400c864f in abort ()
(gdb) up
#3  0x804aef1 in do_read (fd=0, buf=0xbfff932c, sz=16384)
    at ../../../appl/rsh/common.c:68
68                      abort ();
(gdb) l
63                  if (ret != 4)
64                      return -1;
65                  len = ntohl(len);
66                  outer_len = krb5_get_wrapped_length (context, crypto, len);
67                  if (outer_len > sz)
68                      abort ();
69                  ret = krb5_net_read (context, &fd, buf, outer_len);
70                  if (ret != outer_len)
71                      return -1;
72
(gdb) print outer_len
$1 = 16416
(gdb) print sz
$2 = 16384
(gdb) print len
$3 = 16384
(gdb) c
Continuing.

Program terminated with signal SIGABRT, Aborted.
The program no longer exists.
(gdb) 

rsh:
select(9, [0 4 8], NULL, NULL, NULL)    = 1 (in [0])
read(0, "Argument -u\nDirectory .\n/homes"..., 16384) = 413
write(4, "\0\0\1\235", 4)               = 4
write(4, "\346\22\324Rh>^\211\301\301\211\257"..., 448) = 448

(I suspect this is what makes rshd crash - not sure though. It
is the biggest packet sent. Note (1) the 16384 is still
sufficient for the buffer size. (2) this is a different execution
to that below, so the session key will be different.)

rshd:

select(10, [0 7 9], NULL, NULL, NULL)   = 1 (in [7])
read(7, "Valid-requests Root Valid-respon"..., 16384) = 556
write(1, "\0\0\2,", 4)                  = 4
write(1, "\227Ok\20\242\346i\34\7\1g\342H\347"..., 584) = 584
select(10, [0 7 9], NULL, NULL, NULL)   = 1 (in [0])
read(0, "\0\0\0\r", 4)                  = 4
read(0, "\266\3037m\214@\272@_\255d\225Ma"..., 48) = 48
write(6, "UseUnchanged\n", 13)                               = 13
select(10, [0 7 9], NULL, NULL, NULL)   = 1 (in [0])
read(0, "\0\0@\0", 4)                   = 4
sigprocmask(SIG_UNBLOCK, [ABRT], NULL)  = 0
getpid()                                = 29581
kill(29581, SIGABRT)                    = 0
--- SIGABRT (Aborted) ---
+++ killed by SIGABRT +++


> Which brings me to another point: It looks
> like rsh is sending the request to the remote server, in plain text...
> That is the 3-6 write calls to the network scoket, 4, are not encrypted.
> Is this meant to happen? It doesn't look too secure to me...
> 
[...]
> write(4, "bam\0", 4)                    = 4
> write(4, "-x ", 3)                      = 3
> write(4, "cvs server\0", 11)            = 11
> write(4, "bam\0", 4)                    = 4
> write(4, "\0\0\0\0", 4)                 = 4
> read(4, "\0", 1)                        = 1

This disturbs me - I thought the idea behind "-x" was to enable
encryption, but it doesn't seem to apply to the above (inside
send_krb4_auth() and send_krb5_auth()). I would seriously wonder
if it would be possible for an intruder to replace the command
"cvs server" with something else, like "rm -rf ~". There
is something called "cksum_data" which might protect it, but I
am not sure.

-- 
Brian May <bmay@csse.monash.edu.au>