urlichs@smurf.sub.org (Matthias Urlichs) (08/27/90)
It seems that A/UX 2.0(seeding final) doesn't honor the setuid bits when invoking programs via a script. This bothers me because Perl wants #!/usr/local/bin/suidperl in the first line. If I say % suidperl script then the scruipt runs perfectly well. On the other hand, % script (with script of mode 06755) won't do anything except "can't suid" or something, which here means that geteuid() returns non-zero. Does anyone know a reasonable workaround? The only way I've seen is an additional indirection, as in #!/bin/sh exec /usr/lcoal/bin/suidperl script.real Not an ideal solution..? -- Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49+721+621127(Voice)/621227(PEP)
tneff@bfmny0.BFM.COM (Tom Neff) (08/27/90)
In article <1990Aug27.181341.425@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: >Good for it. It's working properly. Suid scripts are a dangerous >security hole. Don't use'em. If you haven't disabled setuid scripts >on your system, do that. Then, put a little C program wrapper around >your script with the following program ... Could someone explain to my dimwitted satisfaction how the security weakness of setuid scripts is corrected by simply exec'ing the scripts from a setuid wrapper?? -- "Don Mattingly is a superstar, so I can justify \)(/ Tom Neff that salary." -- George Steinbrenner, after >()< tneff@bfmny0.BFM.COM signing him for $19.6 million over 5 years. /)(\ uunet!bfmny0!tneff
merlyn@iwarp.intel.com (Randal Schwartz) (08/28/90)
In article <^-i2f2.-42@smurf.sub.org>, urlichs@smurf (Matthias Urlichs) writes: | It seems that A/UX 2.0(seeding final) doesn't honor the setuid bits when | invoking programs via a script. Good for it. It's working properly. Suid scripts are a dangerous security hole. Don't use'em. If you haven't disabled setuid scripts on your system, do that. Then, put a little C program wrapper around your script with the following program (thanks Larry) (by the way, this program is its own manpage in the format that Larry developed... if you don't have pl28 running, throw away anything that doesn't look like a Perl program before execution): ================================================== snip here #!/usr/bin/perl 'di'; 'ig00'; # # $Header$ # # $Log$ if ($#ARGV >= 0) { @list = @ARGV; foreach $name (@ARGV) { die "You must use absolute pathnames.\n" unless $name =~ m|^/|; } } else { open(DF,"/etc/mount|") || die "Can't run /etc/mount"; while (<DF>) { chop; $_ .= <DF> if length($_) < 50; @ary = split; push(@list,$ary[2]) if ($ary[0] =~ m|^/dev|); } } $fslist = join(' ',@list); die "Can't find local filesystems" unless $fslist; open(FIND, "find $fslist -xdev -type f \\( -perm -04000 -o -perm -02000 \\) -print|"); while (<FIND>) { chop; next unless -T; print "Fixing ", $_, "\n"; ($dir,$file) = m|(.*)/(.*)|; chdir $dir || die "Can't chdir to $dir"; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, $blksize,$blocks) = stat($file); die "Can't stat $_" unless $ino; chmod $mode & 01777, $file; # wipe out set[ug]id bits rename($file,".$file"); open(C,">.tmp$$.c") || die "Can't write C program for $_"; $real = "$dir/.$file"; print C ' main(argc,argv) int argc; char **argv; { execv("' . $real . '",argv); } '; close C; system '/bin/cc', ".tmp$$.c", '-o', $file; die "Can't compile new $_" if $?; chmod $mode, $file; chown $uid, $gid, $file; unlink ".tmp$$.c"; chdir '/'; } ############################################################################## # These next few lines are legal in both Perl and nroff. .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 ';__END__ ############# From here on it's a standard manual page ############ .TH SUIDSCRIPT 1 "July 30, 1990" .AT 3 .SH NAME suidscript \- puts a compiled C wrapper around a setuid or setgid script .SH SYNOPSIS .B suidscript [dirlist] .SH DESCRIPTION .I Suidscript creates a small C program to execute a script with setuid or setgid privileges without having to set the setuid or setgid bit on the script, which is a security problem on many machines. Specify the list of directories or files that you wish to process. The names must be absolute pathnames. With no arguments it will attempt to process all the local directories for this machine. The scripts to be processed must have the setuid or setgid bit set. The suidscript program will delete the bits and set them on the wrapper. .PP Non-superusers may only process their own files. .SH ENVIRONMENT No environment varialbes are used. .SH FILES None .SH AUTHOR Larry Wall .SH "SEE ALSO" .SH DIAGNOSTICS .SH BUGS .ex ================================================== snip here eval unpack("u","A<')I;G0@)TIU<W0@86YO=&AE<B!097)L(&AA8VME<BPG") -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
merlyn@iwarp.intel.com (Randal Schwartz) (08/28/90)
In article <15805@bfmny0.BFM.COM>, tneff@bfmny0 (Tom Neff) writes: | In article <1990Aug27.181341.425@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: | >Good for it. It's working properly. Suid scripts are a dangerous | >security hole. Don't use'em. If you haven't disabled setuid scripts | >on your system, do that. Then, put a little C program wrapper around | >your script with the following program ... | | Could someone explain to my dimwitted satisfaction how the security | weakness of setuid scripts is corrected by simply exec'ing the scripts | from a setuid wrapper?? To do so would reveal the whole hole, but hey, what the heck, I heard about it in comp.unix.wizards anyway, so here goes... Theres a small but non-zero window of time between when the system code handling execve() notices the setuid bits and when the file is opened by the shell selected from the #! magic number. During that window, renaming the file (or a link to it... there's a hint) can cause one pile-o-text to be subbed for the other pile-o-text. The first is the "real" script, and the second is your arbitrary program. The net effect is that your abitrary program is executed with the privileges of the "real" script. How big is the window? Big enough to get at from a *shell* program invoking "rm" and "mv" and "ln" (I know, I wrote one)! Sheesh. The wrapper helps because the file executed by the wrapper is explictly named, and short of being able to move *that* file around, you're pretty safe. Just another security weenie and Perl hacker, -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
urlichs@smurf.sub.org (Matthias Urlichs) (08/28/90)
In comp.lang.perl, article <1990Aug27.181341.425@iwarp.intel.com>, merlyn@iwarp.intel.com (Randal Schwartz) writes: < In article <^-i2f2.-42@smurf.sub.org>, urlichs@smurf (Matthias Urlichs) writes: < | It seems that A/UX 2.0(seeding final) doesn't honor the setuid bits when < | invoking programs via a script. < < Good for it. It's working properly. Suid scripts are a dangerous < security hole. Don't use'em. Sorry, Randal, but I was not talking about the setuid bits of the script. (If that wasn't obvious, sorry.) What I have trouble with are the setuid bits of the _program_ (suidperl, in that case), which are also not honored. In that case, there's no security hole, since suidperl will first open the script and then use fstat() to find out about the setuid bits. -- Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49+721+621127(Voice)/621227(PEP)
pvo@sapphire.OCE.ORST.EDU (Paul O'Neill) (08/29/90)
In article <1990Aug27.181341.425@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: > >Good for it. It's working properly. Suid scripts are a dangerous >security hole. Don't use'em. If you haven't disabled setuid scripts >on your system, do that. Then, put a little C program wrapper around >your script with the following program > Hmmmm.... Who's the author of this new book? :-) Preferably you disable setuid scripts and use perl setuid emulation. As a second choice, gift-wrap in C. You don't do both. From the man page: Setuid perl scripts are safer than C programs through a dataflow tracing mechanism which prevents many stupid security holes............... In an unpatched 4.2 or 4.3bsd kernel, setuid scripts are intrinsically insecure, but this kernel feature can be dis- abled. If it is, perl can emulate the setuid and setgid mechanism when it notices the otherwise useless setuid/gid bits on perl scripts. [ie-perl AUTOMAGICALLY invokes suidperl on a setuid perl script IF setuid scripts are disabled.] If the kernel feature isn't disabled, perl will complain loudly that your setuid script is insecure. You'll need to either disable the kernel setuid script feature, or put a C wrapper around the script. [OR, you can cheat, and MANUALLY invoke suidperl. Larry says all bets are off on the security of this approach.] Does your system have setreuid()? You *MAY* want to cheat this way. -----------------From a Larry Wall comp.lang.perl posting:--------------- : I found a great use for suidperl. I invoke it directly on my suid perl : script, or start the suid perl script with the line: : #!/usr/local/bin/suidperl : : And the loud complaining about the kernel patch goes away!! : (Now I get to see all the loud complaining about insecure paths, etc., : neat stuff.) Is this a nasty that should be fixed? Possibly. It is certainly the case that if you put a setuid root csh or sh script on your system, and give me a normal account on your system, I could have root privs within about 2 minutes of the time I find the script. : If so, why? Am I asking for trouble doing this w/o the kernel patches? Possibly, especially if you machine doesn't support setreuid(). The problem is that, because of the aliasing possible with links, there is no way to guarantee that the script opened by the interpreter is in fact the same one that the kernel examined and granted setuid privs to. Now suidperl goes to great lengths to assure that the script you are executing is a set-id script, and that the arguments passed on the command line correspond to the #! line, but it can't assure that it is the same script that the kernel execed. If you have setreuid(), suidperl can swap uid and euid and check that it isn't giving away any privs that the kernel wouldn't give away. If you don't, perl can only use access to check the directory permissions, which is known to have race conditions. (Though perl uses fstat to test the file permissions itself.) So suidperl won't let you run a script that's protected against you, and it won't let you run set-id to anything other than what the script itself is set to, but it can let you run a script in a directory that you don't have access to ordinarily, if you don't have setreuid(). A worse problem is if you decide to bypass the loud message by invoking taintperl rather than suidperl. This also bypasses the checks, because taintperl will assume that it is running a wrapped script. In this case, a setuid perl script is as bad as a setuid shell script--basically gives away the farm. A factor contributing to this is that if setuid is really working, and the uid of the script is not root, then the script uid overrides the suidperl uid, and suidperl will note that it is not running as root, and exit. So your trick only works on setuid root programs. This might tempt you on non-root setuid scripts to use taintperl instead, but that's a losing solution, as pointed out in the previous paragraph. : Can I still : consider my "perl script ... more secure than the corresponding C program"? Maybe. If you have setreuid(), it probably is. But I'm not going to guarantee it if you haven't disabled set-id scripts in the kernel. -------------------------END OF L.WALL QUOTE------------------- Paul O'Neill pvo@oce.orst.edu DoD 000006 Coastal Imaging Lab OSU--Oceanography Corvallis, OR 97331 503-737-3251
worley@compass.com (Dale Worley) (08/29/90)
X-Name: Matthias Urlichs In that case, there's no security hole, since suidperl will first open the script and then use fstat() to find out about the setuid bits. Wouldn't it be possible to put this check into the shell, so setuid shell scripts would be OK? And doesn't suidperl have to also verify that the user is allowed to execute this file, as well as checking the setuid bit? Dale Worley Compass, Inc. worley@compass.com -- The illicit drug business has been described--not entirely in jest--as the best means ever devised by the United States for exporting the capitalist ethic to potentially revolutionary Third World peasants.