NOTE: this the security alert as sent to CERT on 2000-08-08. Though it is formatted as and strongly based on the previous suidperl advisory (http://www.cert.org/advisories/CA-97.17.sperl.html) this is not an official CERT advisory. It has not been issued or checked by CERT. Jarkko Hietaniemi Perl 5.7 development lead UPDATE 2001-04-07: Perl 5.6.1 (released any day now) will contain the proposed fix. Perl 5.7.0 and Perl 5.7.1 (developer releases that will evolve into 5.8.0) contain the proposed fix. CERT never gave an advisory on this, despite my several attempts at getting any response from them. No other platforms than Linux have been reported vulnerable. UPDATE 2000-10-06: For some unknown reason CERT still has not given an advisory on this. I will try to remind them. So far the only platform known to have been vulnerable is Linux, all distributions. No other platforms have been found to be vulnerable. Here are some security advisories given by various Linux distributors. http://www.linuxsecurity.com/advisories/caldera_advisory-607.html http://www.linuxsecurity.com/advisories/debian_advisory-608.html http://www.linuxsecurity.com/advisories/mandrake_advisory-610.html http://www.linuxsecurity.com/advisories/redhat_advisory-647.html http://www.linuxsecurity.com/advisories/slackware_advisory-685.html http://www.linuxsecurity.com/advisories/suse_advisory-630.html http://www.linuxsecurity.com/advisories/turbolinux_advisory-627.html http://www.linuxsecurity.com/advisories/other_advisory-624.html http://www.linuxsecurity.com/advisories/other_advisory-631.html (the two last ones are for the 'Conectiva' and 'Trustix' distributions) --------------------------------------------------------------------------- TOPIC Vulnerability in suidperl (sperl) I. Description On some systems, setuid and setgid scripts (scripts written in the C shell, Bourne shell, or Perl, for example, with the set user or group ID permissions enabled) are insecure due to a race condition in the kernel. For those systems, Perl versions 5 and 4 attempt to work around this vulnerability with an optional component, a special program named suidperl, also known as sperl. This program attempts to emulate the set-user-ID and set-group-ID features of the kernel. There is a vulnerability in suidperl built from any Perl 5.n and Perl 4.n distributions. An exploit kit is available which allows any local user to execute arbitrary commands as root. NOTE: the 'suidperl' component is neither built nor installed by default. II. Impact Local users of a system which has suidperl installed are able to execute arbitrary commands as root. III. Solution Use the instructions in Section III.A to find out whether your system is vulnerable and, if it is, to (optionally) disable the suidperl and sperl programs. If you find that your system is vulnerable, replace the suidperl and sperl programs with new versions, Section III.B describes how to do that if your site uses versions of suidperl and sperl that are provided as part of a vendor-supplied distribution. Sites that installed suidperl and sperl programs themselves from the Perl source distribution should patch the distribution and reinstall perl as described in Section III.C. Note that Perl4 is no longer supported. Section III.A. Determine if your system is vulnerable and disable vulnerable programs A system is vulnerable if both the following conditions are true: (1) you have a program called /bin/mail Try ls -l /bin/mail If this returns something like "not found" or "No such file or directory" you are safe from this particular vulnerability because the exploit depends on using /bin/mail. (2) you have suidperl installed with setuid or setgid rights To determine if a system is vulnerable to this problem and to disable the programs that are believed to be vulnerable, use the following find command or a variant. Consult your local system documentation to determine how to tailor the find program on your system. After you have run this command on all the local filesystems of all all your systems, they will no longer be vulnerable. Note that after disabling the suidperl and sperl programs, they will no longer be able to emulate the set-user-ID and et-group-ID features of the kernel. If some application depended on that functionality, it will no more work. You will need to run the find command on each system you maintain because the command examines files on the local disk only. Substitute the names of your local file systems for FILE_SYSTEM_NAMES in the example. Example local file system names are /, /usr, and /var. You must do this as root. Note that this is one long command, though we have separated it onto four lines using back-slashes. find FILE_SYSTEM_NAMES -xdev -type f \ \( -name 'sperl*' -o -name 'suidperl' \) \ \( -perm -04000 -o -perm -02000 \) \ -print -ok chmod ug-s '{}' \; This command will find all files on a system that are - only in the file system you name (FILE_SYSTEM_NAMES -xdev) - regular files (-type f) - named appropriately (-name 'sperl*' -o -name 'suidperl') - setuid or setgid (-perm -04000 -o -perm -02000) Once found, those files will - have their names printed (-print) - have their modes changed, but only if you type `y' in response to the prompt (-ok chmod ug-s '{}' \;) You can also double check the situation using Perl's own knowledge of where the suidperl would be installed. The usual installation directory for perl executables like suidperl is /usr/bin but you should check the output of perl -V:installbin If that is something else than installbin='/usr/bin'; you should run perl -MConfig -e '$ib = $Config{installbin}; for ("sperl*", "suidperl") {system("ls -l $ib/$_")}' If this shows something like -rwsr-xr-x 2 root bin 12345678 Mar 27 21:54 /opt/bin/sperl5.00503 -rwsr-xr-x 2 root bin 12345678 Mar 27 21:54 /opt/bin/suidperl or -rw-r-sr-x 2 root bin 12345678 Mar 27 21:54 /opt/bin/sperl5.00503 -rw-r-sr-x 2 root bin 12345678 Mar 27 21:54 /opt/bin/suidperl you still have setuid or setgid perls (the 's' in the 4th or 7th columns) and you should use chmod to disable the setuid and setgid rights: chmod ug-s /opt/bin/sperl* /opt/bin/suidperl Section III.B. If your vendor ships suidperl or sperl, you may be vulnerable and need a patch. Appendix A contains information provided by the following vendors. If your vendor is not on this list, please contact the vendor directly. [TBD] Until you can install a patch, we recommend disabling suidperl as described in Section III.A. The find command above will help you do that. If you need suidperl or sperl, see the alternatives in Section III.C below. Section III.C. Install suidperl or sperl from 5.6.0 source code and apply a patch. If you would like to keep using setuid Perl scripts, fix Perl yourself by following these steps: 1. Go to your Perl 5.6.0 source directory, or else obtain a a fresh Perl 5.6.0 distribution from http://www.cpan.org/CPAN/src/5.0/perl-5.6.0.tar.gz or another CPAN archive accessible to you: http://www.cpan.org/CPAN/SITES.html This file is approximately 5.4 megabytes in size. 2. Using the "patch" program, apply the patch that is enclosed below in Appendix B.1. 3. Build and install the patched Perl 5.6.0. If you have never built Perl before, be sure to read the "INSTALL" file first. The steps in more detail, this should work for most sites. 1.0 Assuming the source code kit and the patch have already been downloaded to the current directory... 1.1. Unpack the source code kit gunzip perl-5.6.0.tar.gz tar xf perl-5.6.0.tar 2.1. Change to the source code directory cd perl-5.6.0 2.2. Apply the patch patch -p1 < ../sperl-5.6.0-2000-08-05.patch 3.1. Configure sh ./Configure -ders 3.2. Rebuild and test make all test If everything went fine, the "test" target will in the end output "All tests successful." 3.3. Install make install Perl 5.6.0 binaries that have had this patch applied, and therefore are safe from all known attacks, can be identified by the output of the "perl -V" command: the "Locally applied patches" list will include "SUIDMAIL - fixes for suidperl security". Some sites may for stability reasons prefer to patch and reinstall some earlier version of Perl. The Appendix B contains the patches for 5.6.0 and for releases that are still known to be in widespread use: 5.005_03, 5.004_05, and 5.004_04. Any earlier release is very much unsupported. Upgrade to (patched) Perl 5.6.0 is encouraged. --------------------------------------------------------------------------- Appendix A - Vendor Information [unofficial, seen in bugtraq: Redhat 6.* and 7.0 are vulnerable, as is Mandrake 6.0] [TBD] --------------------------------------------------------------------------- Appendix B - Source Code Patch Information In addition to being shown here the source code patches will be available also at http://www.cpan.org/src/5.0/sperl-2000-08-05/ For details about the patch, see Appendix C. B.1. Patch for perl 5.6.0: diff -rc perl-5.6.0.dist/patchlevel.h perl-5.6.0/patchlevel.h *** perl-5.6.0.dist/patchlevel.h Wed Mar 22 22:23:11 2000 --- perl-5.6.0/patchlevel.h Tue Aug 8 03:06:46 2000 *************** *** 69,75 **** */ #if !defined(PERL_PATCHLEVEL_H_IMPLICIT) && !defined(LOCAL_PATCH_COUNT) static char *local_patches[] = { ! NULL ,NULL }; --- 69,76 ---- */ #if !defined(PERL_PATCHLEVEL_H_IMPLICIT) && !defined(LOCAL_PATCH_COUNT) static char *local_patches[] = { ! NULL ! ,"SUIDMAIL - fixes for suidperl security" ,NULL }; diff -rc perl-5.6.0.dist/perl.c perl-5.6.0/perl.c *** perl-5.6.0.dist/perl.c Sat Mar 18 00:35:15 2000 --- perl-5.6.0/perl.c Mon Aug 7 20:56:56 2000 *************** *** 2758,2773 **** if (tmpstatbuf.st_dev != PL_statbuf.st_dev || tmpstatbuf.st_ino != PL_statbuf.st_ino) { (void)PerlIO_close(PL_rsfp); - if (PL_rsfp = PerlProc_popen("/bin/mail root","w")) { /* heh, heh */ - PerlIO_printf(PL_rsfp, - "User %"Uid_t_f" tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\ - (Filename of set-id script was %s, uid %"Uid_t_f" gid %"Gid_t_f".)\n\nSincerely,\nperl\n", - PL_uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino, - (long)PL_statbuf.st_dev, (long)PL_statbuf.st_ino, - CopFILE(PL_curcop), - PL_statbuf.st_uid, PL_statbuf.st_gid); - (void)PerlProc_pclose(PL_rsfp); - } Perl_croak(aTHX_ "Permission denied\n"); } if ( --- 2758,2763 ---- (end of patch for perl 5.6.0) B.2. Patch for perl 5.005_03: diff -rc perl5.005_03.dist/patchlevel.h perl5.005_03/patchlevel.h *** perl5.005_03.dist/patchlevel.h Sun Mar 28 19:11:58 1999 --- perl5.005_03/patchlevel.h Tue Aug 8 03:06:39 2000 *************** *** 40,45 **** --- 40,46 ---- */ static char *local_patches[] = { NULL + ,"SUIDMAIL - fixes for suidperl security" ,NULL }; diff -rc perl5.005_03.dist/perl.c perl5.005_03/perl.c *** perl5.005_03.dist/perl.c Sat Mar 27 19:49:17 1999 --- perl5.005_03/perl.c Mon Aug 7 20:57:45 2000 *************** *** 2220,2235 **** if (tmpstatbuf.st_dev != PL_statbuf.st_dev || tmpstatbuf.st_ino != PL_statbuf.st_ino) { (void)PerlIO_close(PL_rsfp); - if (PL_rsfp = PerlProc_popen("/bin/mail root","w")) { /* heh, heh */ - PerlIO_printf(PL_rsfp, - "User %ld tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\ - (Filename of set-id script was %s, uid %ld gid %ld.)\n\nSincerely,\nperl\n", - (long)PL_uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino, - (long)PL_statbuf.st_dev, (long)PL_statbuf.st_ino, - SvPVX(GvSV(PL_curcop->cop_filegv)), - (long)PL_statbuf.st_uid, (long)PL_statbuf.st_gid); - (void)PerlProc_pclose(PL_rsfp); - } croak("Permission denied\n"); } if ( --- 2220,2225 ---- (end of patch for perl 5.005_03) B.3. Patch for perl 5.004_05: diff -rc perl5.004_05.dist/patchlevel.h perl5.004_05/patchlevel.h *** perl5.004_05.dist/patchlevel.h Thu Apr 29 17:54:58 1999 --- perl5.004_05/patchlevel.h Tue Aug 8 03:08:02 2000 *************** *** 39,44 **** --- 39,45 ---- /* The following line and terminating '};' are read by perlbug.PL. Don't alter. */ static char *local_patches[] = { NULL + ,"SUIDMAIL - fixes for suidperl security" ,NULL }; diff -rc perl5.004_05.dist/perl.c perl5.004_05/perl.c *** perl5.004_05.dist/perl.c Tue Apr 6 22:38:11 1999 --- perl5.004_05/perl.c Mon Aug 7 21:03:57 2000 *************** *** 1926,1941 **** if (tmpstatbuf.st_dev != statbuf.st_dev || tmpstatbuf.st_ino != statbuf.st_ino) { (void)PerlIO_close(rsfp); - if (rsfp = my_popen("/bin/mail root","w")) { /* heh, heh */ - PerlIO_printf(rsfp, - "User %ld tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\ - (Filename of set-id script was %s, uid %ld gid %ld.)\n\nSincerely,\nperl\n", - (long)uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino, - (long)statbuf.st_dev, (long)statbuf.st_ino, - SvPVX(GvSV(curcop->cop_filegv)), - (long)statbuf.st_uid, (long)statbuf.st_gid); - (void)my_pclose(rsfp); - } croak("Permission denied\n"); } if ( --- 1926,1931 ---- (end of patch for perl 5.004_05) B.4. Patch for perl 5.004_04: diff -rc perl5.004_04.dist/patchlevel.h perl5.004_04/patchlevel.h *** perl5.004_04.dist/patchlevel.h Wed Oct 15 12:55:19 1997 --- perl5.004_04/patchlevel.h Tue Aug 8 03:10:03 2000 *************** *** 39,44 **** --- 39,45 ---- /* The following line and terminating '};' are read by perlbug.PL. Don't alter. */ static char *local_patches[] = { NULL + ,"SUIDMAIL - fixes for suidperl security" ,NULL }; diff -rc perl5.004_04.dist/perl.c perl5.004_04/perl.c *** perl5.004_04.dist/perl.c Tue Oct 14 21:09:18 1997 --- perl5.004_04/perl.c Mon Aug 7 21:37:51 2000 *************** *** 2039,2054 **** if (tmpstatbuf.st_dev != statbuf.st_dev || tmpstatbuf.st_ino != statbuf.st_ino) { (void)PerlIO_close(rsfp); - if (rsfp = my_popen("/bin/mail root","w")) { /* heh, heh */ - PerlIO_printf(rsfp, - "User %ld tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\ - (Filename of set-id script was %s, uid %ld gid %ld.)\n\nSincerely,\nperl\n", - (long)uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino, - (long)statbuf.st_dev, (long)statbuf.st_ino, - SvPVX(GvSV(curcop->cop_filegv)), - (long)statbuf.st_uid, (long)statbuf.st_gid); - (void)my_pclose(rsfp); - } croak("Permission denied\n"); } if ( --- 2039,2044 ---- (end of patch for perl 5.004_04) ------------------------------------------------------------------------ Appendix C - The Exploit and Patch Details The bug was reported by Michal Zalewski on Saturday, 2000-Aug-05, in a bugtraq security mailing list message [2] titled "sperl 5.00503 (and newer ;) exploit". Included in the message as also an exploit kit. The cause of the vulnerability is, ironically enough, Perl trying to report a suspected security incident, by sending email to the root account using the external /bin/mail program. Unfortunately /bin/mail is too featureful and can be tricked into giving an interactive shell instead of sending email. The shell inherits the superuser rights. The supplied patches are rather blunt: they simply remove the sending of the email message. At later point a more elegant fix may be supplied that retains the feature, if the feature is considered worth it. [1] Message-id Here is a link to the message in the bugtraq mailing list archives: http://www.securityfocus.com/frames/?content=/templates/archive.pike%3Flist%3D1%26date%3D2000-08-01%26msg%3DPine.LNX.4.21.0008051825300.26685-101000%40dione.ids.pl ------------------------------------------------------------------------