Bugtraq mailing list archives

Re: sperl 5.00503 (and newer ;) exploit


From: Simon Cozens <simon () OTHERSIDEOFTHE EARTH LI>
Date: Tue, 8 Aug 2000 06:23:50 -0000

In lists.security, you wrote:
Looking for further problems, I checked 'strings suidperl' and it shows
(besides the mail thing, and lots of irrelevant stuff):

/usr/bin/csh

You didn't say which version of Perl this was from, but versions prior
to 5.6.0 use csh for globbing. ("<*.foo>" and so on.)

I *believe* this was sanity checked for naughty input ("<*|rm -rf />") etc.
but I can't verify that right now because I don't have <5.6.0 handy, but
even if not, this would require programmer insecurity, not Perl insecurity.

By which I mean, if you're writing
    @foo = <*|rm -rf />;
in a setuid script, you get what's coming to you. If you're doing that
with *external input* in a suid root program, you deserve to be hung, drawn,
quartered and then really, really hurt.

/usr/bin/sed
-e '1,/^#/d

This is mega-rare. It's used in perl.c when both the -P and -x options are
passed to Perl to extract the Perl bit of the program before it's passed to
cpp. In suidperl, root privileges are dropped before the pipe to sed and cpp
is opened:

perl.c, with the #defines tidied up:

    Perl_sv_setpvf(aTHX_ cmd, "\
%s %s -e '/^[^#]/b' \
 -e '/^#[   ]*include[  ]/b' \
.....
 %s | %"SVf" -C %"SVf" %s",
      "sed",
      (PL_doextract ? "-e '1,/^#/d\n'" : ""),
      scriptname, cpp, sv, CPPMINUS);
    PL_doextract = FALSE;
    if (PL_euid != PL_uid && !PL_euid) {    /* if running suidperl */
#ifdef HAS_SETEUID
        (void)seteuid(PL_uid);      /* musn't stay setuid root */
#else
#ifdef HAS_SETREUID
        (void)setreuid((Uid_t)-1, PL_uid);
#else
        (void)setresuid((Uid_t)-1, PL_uid, (Uid_t)-1);
#endif
#endif
        if (PerlProc_geteuid() != PL_uid)
        Perl_croak(aTHX_ "Can't do seteuid!\n");
    }
    PL_rsfp = PerlProc_popen(SvPVX(cmd), "r");

/bin/sh

A shell is invoked when an external program is spawned and shell
metacharacter processing is requested, such as:

    open(FOO, "| grok *") or die $!;
    system("grok *.*");
    `grok *`;

This is documented, and the same programmer error caveat applies as above.

If you're doing things like this in your Perl programs and you don't want to
invoke a shell, do the globbing and whatever other processing you need
directly, (Perl handles filehandle redirections such as 2>&1 internally, but
not, IIRC, 2>foo) and then:

    open(FOO, "|", "grok", @arguments)
    system("grok",@arguments);

This will exec grok without spawning a shell. See perldoc -f system for
more information on that.

Hope this helps!
Simon

--
"He was a modest, good-humored boy.  It was Oxford that made him insufferable."


Current thread: