Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

setuid: Perl v C

by eyepopslikeamosquito (Chancellor)
on May 05, 2003 at 06:23 UTC ( #255570=perlquestion: print w/replies, xml ) Need Help??

eyepopslikeamosquito has asked for the wisdom of the Perl Monks concerning the following question:

I have a large shell script that I want to make setuid. Someone suggested rewriting it in C. I would prefer to rewrite it in Perl, if possible. Generally, are setuid programs more secure in C than in Perl? Specifically, I plan to make the following steps. If anyone sees any reason why this will be less secure than a pure C solution, please let me know. Other suggestions are also welcome.

wr.c (C wrapper): #include <unistd.h> main(int argc, char* argv[]) { char* sArgv[8]; sArgv[0] = (char*)"/usr/bin/perl"; sArgv[1] = (char*)"-wT"; sArgv[2] = (char*)"/home/fred/setuid/"; sArgv[3] = argv[1]; sArgv[4] = 0; execv("/usr/bin/perl", sArgv); }

For various reasons, I prefer not to use a shebang line in the Perl script, and will not use /usr/bin/perl but my own custom version.

Example Perl script use strict; sub dump_user_details { my $uid = shift; my ($user, $u, $pgid, $home, $shell) = (getpwuid($uid))[0,2,3,7,8]; print "ruid='$<' euid='$>' uid='$uid' u='$u' pgid='$pgid'\n"; print "user='$user' home='$home' shell='$shell'\n"; my @gids = ( $pgid ); while (my ($name, $pw, $gid, $members) = getgrent) { push(@gids, $gid) if grep($_ eq $user, split(' ', $members)); } endgrent(); print "gids:@gids:\n"; } my $arg1 = shift; print "arg1='$arg1'\n"; dump_user_details($<); dump_user_details($>) if $> != $<;

Then issue the following commands:

cc -o wr wr.c chown root wr chmod 700 chmod 4710 wr ./wr test

Replies are listed 'Best First'.
Re: setuid: Perl v C
by tachyon (Chancellor) on May 05, 2003 at 06:53 UTC

    As Zaxo point out you can't have suid root scripts ie perl on Linux. I use sudo as he suggests and find it works well. For example I have an application that I need to have CGI scripts be able to send SIG HUPs to. The CGI scripts don't have sufficient permissions running as user apache to do this so this is how I set it up so they can do it:

    #!/usr/bin/perl -w # # this script needs to be run as root, to do this we add an entry to # /etc/sudoers so that just apache can run it suid root # NB: you must edit this file using visudo, ie # visudo -f /etc/sudoers # add this line # apache ALL=NOPASSWD:/home/scripts/ # In CGI call as system('sudo', '/home/scripts/'); my $PROGRAM = ''; @ps = `ps ax`; @ps = map { m/(\d+)/; $1 } grep { /\Q$PROGRAM\E/ } @ps; # for debugging lets see who we think we are.... #printf("uid=%d euid=%d<br>\n", $<, $>); for ( @ps ) { (kill HUP, $_) or exit 42; } my $time = gmtime(); warn "[$time] Sent SIGHUP to $PROGRAM @ps\n"; exit 0;

    By using sudo then the script is not suid per se but a CGI can run it suid root (and only this script)




Re: setuid: Perl v C
by Zaxo (Archbishop) on May 05, 2003 at 06:33 UTC

    You might take a look at sudo. You don't say how you plan to run your script, but some OS's (like Linux) won't let you run an interpreter script suid root.

    Is root privilege really necessary? What are you doing that seems to need it?

    After Compline,

      In my little example, the C wrapper wr is setuid, not the interpreter (I am not attempting to use the suidperl binary). The example I posted seems to work fine on Linux. The C wrapper technique I am using is mentioned near the end of perlsec; if I am missing something here, please let me know, as I am no security guru.

      The script is to run at many customer sites and it is unacceptable to ask them to install sudo. The people who run it may not have the root password yet root permissions are required to mess with installing/loading device drivers (which is what the script does).

Re: setuid: Perl v C
by grinder (Bishop) on May 05, 2003 at 12:53 UTC
    Generally, are setuid programs more secure in C than in Perl?

    Generally, with a whole lot of caveats and provisos in mind, Perl scripts are more secure than C scripts. The basic reasoning is as follows:

    The main source of compromises comes about through buffer overflows. You might have the following line of code in C:

    char password[32];

    ... because no-one has passwords longer than 32 characters, right? Crackers will force arbitrarily long strings into this variable to see what happens. With a bit of luck they'll clobber the return frame on the stack, and if the string is crafted just so, they'll succeed in getting the program to jump to a completely unrelated area of memory that just so happens to contain a bunch of machine instructions that they placed there beforehand. Bingo! you are 0wn3d.

    This is much harder to do in Perl, because scalar variables don't have a built-in notion of maximum length. A scalar will just keep growing as required. You can't overflow them, bar exhausting virtual machine memory.

    Yes, this is avoidable in C, but it is hard to do right.

    More sorts of trickery can be performed by diddling with pointers. In Perl you can't just write something like:

    my $x = 'SCALAR(0x8101730)';

    ... and magically expect to start peering at some odd corner of memory. Since you're one level of abstraction away from the machine, it's harder to break into it.

    And plus, as you appear to be doing in your example, taint mode helps look after details that you might forget about. The truly paranoid would also audit every single line of each module used, whether it be part of the core distribution or stuff you installed from CPAN.

    Come to YAPC::Europe 2003 in Paris, 23-25 July 2003.

Re: setuid: Perl v C
by grantm (Parson) on May 05, 2003 at 09:07 UTC

    I'd like to add my vote to the sudo camp. In fact for the best security, I'd say don't run the script from sudo, but call sudo from the script at the point(s) you need elevated priviliges. That way you localise the bits that you need to be extra wary of.

Re: setuid: Perl v C
by Anonymous Monk on May 05, 2003 at 16:50 UTC
    In general, setuid programs are less secure in C than in Perl, not only because of buffer overflow exploits, but also because C doesn't know how to do taint checks.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://255570]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2020-01-26 01:40 GMT
Find Nodes?
    Voting Booth?