in reply to perl 5.16 setuid

The clean way to execute perl code setuid is to compile a wrapper from six lines of C code. See Security Bugs in perlsec.

Update:

This is the code from perlsec:

#define REAL_PATH "/path/to/script" main(ac, av) char **av; { execv(REAL_PATH, av); }

It is K&R style, quick and dirty, but it works.

If you prefer modern code that compiles cleanly even with gcc -Wall -pedantic, and that reports an error when executing the script fails, try this:

#include <unistd.h> /* for execv() */ #include <stdio.h> /* for perror() */ #define REAL_PATH "/path/to/script" int main(int argc, char ** argv) { execv(REAL_PATH, argv); perror("Can't execute main script"); return 126; }

Note that the wrapper is setuid, not the script. The script inherits the setuid from the wrapper.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Replies are listed 'Best First'.
Re^2: perl 5.16 setuid
by Corion (Patriarch) on Oct 14, 2016 at 12:23 UTC

    This change from K&R to C89 has now found its way into Perl at 245c138e. Thanks to you and mauke for putting in the hard work.

Re^2: perl 5.16 setuid
by Anonymous Monk on Apr 30, 2018 at 19:00 UTC
    There is a problem with this method. If the 'C' wrapper is used the script it points to must be secured with 750 or 755 and owned by root or the user it is switching to. Otherwise, you have a real problem with someone being able to write anything they want to the script since the SUID tamper security is only on the wrapper and not on the script. Also, make sure to still use the following header in the script so it will complain about unsafe code. And finally monitor all your scripts called from wrappers for changes with something like inotifywait/inotifywatch or other file monitoring tool.

    #!/usr/bin/perl -T

    Hope this helps someone.

      The world-writable checks (on every path directory as well as the file itself) are understood and a good security practice, certainly. But could you please elaborate on the inotify suggestion? How would one read the inotify events, and perform an execve() at the same time without any race conditions arising?