in reply to Perl script needs root privilegies

A much better option than suid-ing a script IMO is to use sudo to give your user exactly the capabilities he needs. For example, if you put this in your /etc/sudoers file:

nobody: ALL=(ALL) NOPASSWD:/sbin/iptables

Your user nobody will be able to call sudo iptables and it will execute as root without the need to enter a password. Personally this would not be quite paranoid enough for me, I'd prefer to write separate shell scripts which execute exactly the iptables command I want the user to be able to execute and specify these explicitly in sudoers, but YMMV.


A computer is a state machine. Threads are for people who can't program state machines. -- Alan Cox

Replies are listed 'Best First'.
Re^2: Perl script needs root privilegies
by ivanatora (Sexton) on Dec 26, 2005 at 11:38 UTC
    SUDO would be nice if I had only iptables. But this script uses a whole bunch of programs, not only iptables. I can't write them all down to /etc/sudoers ;)
    I thought there is some generic perl way to change uid?
      I can't write them all down to /etc/sudoers

      Umm, why not? This is an extremely flexible and comfortable way of granting minimum necessary privileges (you can even give users the ability to run commands as other users, not root, or use one sudoers file for several systems, specifying which capabilities are allowed on which systems). Why would you not want to do this the most secure way possible (given that what you're trying to do is risky at best anyway)?

      I thought there is some generic perl way to change uid?

      Sorry, I'm not in the business of promoting bad practices (and I consider suidperl to be a bad practice :-).

      If you're calling lots of external commands, the best thing would be to condense these into one or several shell scripts (taking care to make the scripts do as little as possible, be as unambiguous as possible and require as few passed parameters as possible) and then make the script callable by sudo.


      A computer is a state machine. Threads are for people who can't program state machines. -- Alan Cox
        Ok, lets say you convinced me for now ;)
        I had in mind that there must be another way to make that. I'm not against sudo, I use it for a cople of another scripts. I thought that it will be dangerous overcrouded there if I add all needed programs for that script there.

      You can change your uid in Perl by using POSIX::setuid, but setting your userid only works if you are already on uid 0. Also, using setuid programs or scripts is a dangerous practice, so I would try to limit what needs to be done by root as much as possible.

Re^2: Perl script needs root privilegies
by Celada (Monk) on Dec 27, 2005 at 18:54 UTC
    nobody: ALL=(ALL) NOPASSWD:/sbin/iptables

    Eek! Now all of the CGI scripts, mod_perl code and everything else that runs anonymously under the web server, PLUS everything else that runs under user nobody on the system, including things like a font server, will be able to run this command!

    The best approach in my opinion is to combine both:

    1. Script is setuid to a dedicated user that runs only that script, and
    2. That dedicated user is only allowed to run a couple of key commands via sudo.

    But if I had to choose and use only one approach, I'd pick the OP's.

    Now as to how to make the script setuid in the first place, that depends. If you have an operating system like Solaris that has secure setuid scripts, it will work directly. Otherwise you have the suidperl can of worms. As an alternative, the web server might make use of suExec and you may be able to get that to cause your script to run under the correct user ID.

    In any case, don't forget to turn on taint checks if they're not turned on automatically for whatever invocation style you end up using (they are turned on automatically for true setuid scripts.

      You missed out my following statement "I'd prefer to write separate shell scripts which execute exactly the iptables command I want the user to be able to execute" :-). Which would you rather have, /sbin/iptables that is setuid and user-executable (which nobody advocated, for good reason) or my line in sudoers? Same thing goes for scripts you write yourself.


      A computer is a state machine. Threads are for people who can't program state machines. -- Alan Cox

        Which would you rather have, /sbin/iptables that is setuid and user-executable (which nobody advocated, for good reason) or my line in sudoers? Same thing goes for scripts you write yourself.

        Actually those two choices are quite similar (control access to iptables via file permissions or control access via sudoers). I would have neither. I must stress again that the line you suggested for inclusion in sudoers lets you run any iptables command you want (in other words: run iptables with any arguments you want) as long as you are user nobody. Since on the OP's system nobody is the web server account, lots of code runs as that user and will have access to run iptables. Indeed on mostly any system there's usually some piece of code that runs as user nobody that should not be trusted with iptables privileges.

        Obviously the goal is for unprivileged users to be able to cause iptables commands to be executed, but the goal is to only permit those iptables commands that the application specifically requires. Which iptables commands get executed is only under the indirect control of the user, according to what the CGI script will choose to honour. That's why the limited API between the client's user agent and the CGI needs to be the where the barrier between security domains is located (or equivalently, the CGI can call a backend that provides an API that is not more powerful than the one facing the user agent; some other monks suggested that).

        All of this of course assumes that the CGI actually limits what the end user can cause iptables to do. If the CGI script is the following code, then all bets are off!

        use CGI qw/standard/; system("iptables " . param("iptables_command"));
Re^2: Perl script needs root privilegies
by blazar (Canon) on Dec 27, 2005 at 14:22 UTC
    A much better option than suid-ing a script IMO is to use sudo to give your user exactly the capabilities he needs. For example, if you put this in your /etc/sudoers file:

    And another option would be to have another program with appropriate permissions running as a separate process and do the critical jobs: this would require some form of IPC, but may even be done asyinchronously if such an option is suitable for the actual application.

    For example the firewall script may add entries to a file (which may also happen to be a named pipe) and another script may process them running the necessary programs requiring root privileges.