I am trying to add a function to an obsolete script. The script is suid and uses perl -T (taint mode: man perlsec) for added security. The function I need to add is implemented in Python.
My problem is that I cannot convince perlsec to retain suid rights no matter how much I clean up the environment and my command lines.
This is frustrating since it saves suid for other binaries (such as / bin / id). Is there an undocumented special case for / usr / bin / perl? This seems unlikely.
Does anyone know a way to make this work? ( As-is : we donβt have the resources to reverse engineer it all.)
Solution: (according to @gbacon)
# use the -p option to bash system('/bin/bash', '-p', '-c', '/usr/bin/id -un');
Gives the desired results!
Here is a cut out version of my script that still shows my problem.
#!/usr/bin/perl -T ## This is an SUID script: man perlsec %ENV = ( "PATH" => "" ); ##### PERLSEC HELPERS ##### sub tainted (@) { # Prevent errors, stringifying local(@_, $@ , $^W) = @_; #let eval catch the DIE signal $SIG{__DIE__} = ''; my $retval = not eval { join("",@_), kill 0; 1 }; $SIG{__DIE__} = 'myexit'; return $retval } sub show_taint { foreach (@_) { my $arg = $_; #prevent "read-only variable" nonsense chomp $arg; if ( tainted($arg) ) { print "TAINT:'$arg'"; } else { print "ok:'$arg'"; } print ", "; } print "\n"; } ### END PERLSEC HELPERS ### # Are we SUID ? man perlsec my $uid = `/usr/bin/id --user` ; chomp $uid; my $reluser = "dt-pdrel"; my $reluid = `/usr/bin/id --user $reluser 2> /dev/null`; chomp $reluid; if ( $uid ne $reluid ) { # what ? we are not anymore SUID ? somebody must do a chmod u+s $current_script print STDERR "chmod 4555 $myname\n"; exit(14); } # comment this line if you don't want to autoflush after every print $| = 1; # now, we're safe, single & SUID # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # BEGIN of main code itself print "\nENVIRON UNDER BASH:\n"; run('/bin/bash', '-c', '/bin/env'); print "\nTAINT DEMO:\n"; print "\@ARGV: "; show_taint(@ARGV); print "\%ENV: "; show_taint(values %ENV); print "`cat`: "; show_taint(`/bin/cat /etc/host.conf`); print "\nworks:\n"; run('/usr/bin/id', '-un'); run('/usr/bin/id -un'); print "\ndoesn't work:\n"; run('/bin/bash', '-c', '/usr/bin/id -un'); run('/bin/bash', '-c', '/bin/date >> /home/dt-pdrel/date'); run('/bin/date >> /home/dt-pdrel/date'); run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")'); run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")'); sub run { my @cmd = @_; print "\tCMD: '@cmd'\n"; print "\tSEC: "; show_taint(@cmd); print "\tOUT: "; system @cmd ; print "\n"; }
And here is the conclusion:
$ id -un bukzor $ ls -l /proj/test/test.pl -rwsr-xr-x 1 testrel asic 1976 Jul 22 14:34 /proj/test/test.pl* $ /proj/test/test.pl foo bar ENVIRON UNDER BASH: CMD: '/bin/bash -c /bin/env' SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/env', OUT: PATH= PWD=/proj/test2/bukzor/test_dir/ SHLVL=1 _=/bin/env TAINT DEMO: @ARGV: TAINT:'foo', TAINT:'bar', %ENV: ok:'', `cat`: TAINT:'order hosts,bind', works: CMD: '/usr/bin/id -un' SEC: ok:'/usr/bin/id', ok:'-un', OUT: testrel CMD: '/usr/bin/id -un' SEC: ok:'/usr/bin/id -un', OUT: testrel doesn't work: CMD: '/bin/bash -c /usr/bin/id -un' SEC: ok:'/bin/bash', ok:'-c', ok:'/usr/bin/id -un', OUT: bukzor CMD: '/bin/bash -c /bin/date >> /home/testrel/date' SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/date >> /home/testrel/date', OUT: /bin/bash: /home/testrel/date: Permission denied CMD: '/bin/date >> /home/testrel/date' SEC: ok:'/bin/date >> /home/testrel/date', OUT: sh: /home/testrel/date: Permission denied CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")' SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")', OUT: bukzor CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")' SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")', OUT: bukzor