Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Security, root and CGI?

by pileofrogs (Priest)
on Jan 28, 2009 at 22:56 UTC ( #739721=perlquestion: print w/replies, xml ) Need Help??

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

Greetings, ye monks!

I'm going to write a web front-end to some sysadmin things that I do. This is to allow users to do things themselves that I'm sicking of doing by hand. I'm on linux. I want to separate the must-run-as-root code from the web code.

I'm thinking I'll have a CGI script and a seperate runs-as-root-script. The runs-as-root-script will do the actual privileged actions and the CGI will gather input from users and and pass the particulars onto the runs-as-root bit. I'm thinking the runs-as-root bit will be a constantly running service, so as to avoid suid. The cgi could talk to the run-as-root bit with unix sockets or something of that nature.

As I see it, I'll need to authenticate the users twice: first in the CGI and second in the runs-as-root bit. I want to authenticate in the CGI so I can give users feedback, avoid bothering the runs-as-root bit unnecessarily and so on. I need to authenticate in the runs-as-root bit because even if I authenticate in the CGI, I don't think there's a way the runs-as-root bit can entirely trust the cgi or that a request is coming from the cgi. The cgi handles user interface and makes it possible for the runs-as-root bit to have a very limited, strictly-defined interface.

In case I'm being unclear (my usual state) here's kindof how I envision a request going:

User -> web browser -> cgi -> runs-as-root -> system

So only the runs as root bit needs to run as root.

My first and most important question is: does this make sense? Is it a dumb idea? Am I making this too complex?.

My second question is: What's the best way to communicate between the cgi and the runs-as-root stuff? Is there any interprocess communication that guarantees input comes from a particular script? Security is my #1 priority.

I hope this question is comprehensible, and thanks for any thoughts.


Replies are listed 'Best First'.
Re: Security, root and CGI?
by MidLifeXis (Monsignor) on Jan 28, 2009 at 23:20 UTC

    At some point, your runs-as-root part needs to trust the job being submitted to it. What level of security is needed to get this trust high enough? What do you, as the SA, require the user to prove to you before you act on their request? Now, what is needed to have a program do the same thing?

    Be careful about file system permissions. Perhaps run the CGI submitter under a suexec setup to allow only that CGI to touch whatever mechanism is used to pass information to run-as-root. Think "minimum privilege necessary".


      I'm planning on using an suexec like thing (CGIWrap). I don't know of any mechanisms that could be limited by the UID of the CGI process. Maybe a socket? Are there others?

Re: Security, root and CGI?
by Rodster001 (Pilgrim) on Jan 29, 2009 at 00:00 UTC
    In cases like this I usually touch a file somewhere safe on the file system or insert a row into a database. Then I have a cron run every minute (or however often required) that checks for said file or database row, and if it finds it, does what it is suppose to do. This way the event is simply triggered via the web and you don't have to have anything running as root.
Re: Security, root and CGI?
by Anonymous Monk on Jan 29, 2009 at 00:15 UTC
    Some web hosting control panels work this same way: Monster Controls is just one that comes to mind. Your approach with the various components has been done before and it makes sense. Since security is #1, your service should only accept instruction verified to have come from the cgi and that it came from an authorized user (you). You might be able to do this with public / private key crypto: Provide your application your private key (or your passphrase to your private key) to encrypt messages bound for the service, and let the service decrypt messages with your public key. The question then becomes how much do you trust your cgi application? Or your browser? But I think that's a different topic - if somebody compromised the cgi, they could capture your passphrase or key, and if somebody compromised your browser (desktop), they could key-log your passphrase / key.
Re: Security, root and CGI?
by Plankton (Vicar) on Jan 29, 2009 at 01:01 UTC
    I image that somewhere down the line your CGI will eventually execute command line/system utilities. You should probably become very familiar with sudo and the /etc/sudoers file. You'll want to configure sudo to limit the commands that your CGI (or the user your CGI scripts will run as) can run.
Re: Security, root and CGI?
by hbm (Hermit) on Jan 29, 2009 at 01:52 UTC

    I'd run the web server as a UID that 1) has no shell access; and 2) has no ownership outside the web server. And 3) allow that (and only that) UID to run the root script via sudo.

    On the other hand, I'm pressed to think of any root-owned tasks that I'd unload... Do they need to be owned by root? Can they not be cron'd?

Re: Security, root and CGI?
by dietbuddha (Sexton) on Jan 29, 2009 at 08:05 UTC

    My 2.

    Don't write it yourself if someone else has already written it had more testing.

    Especially avoid writing it yourself if it has to do with privileged execution.

    Failing to find something thats already been written, don't write a daemon that runs with root privileges. You can use at (man at(1)) to queue up the execution of scripts that do the absolute minimum, ideally in a jail.

Re: Security, root and CGI?
by DrHyde (Prior) on Jan 29, 2009 at 11:39 UTC

    It makes sense. In fact it's quite common to do this, although with authentication in the CGI. The one change I'd make is that instead of doing authentication in both the CGI and the root daemon, I'd only do it in the root daemon, and have the CGI ask it what actions a particular user can perform so that it can present the right options to him. Then, obviously, when the CGI actually submits a job to the root daemon, the daemon needs to authenticate it again.

    I'm not sure that you can guarantee that communications are coming from a particular process. But then, provided that you authenticate before performing each action as root, that shouldn't matter. If someone manages to talk to your process in a way you didn't expect, then if they can't authenticate that's great, if they can - well, so what? They could just as easily authenticate through your web interface.

    You might even find it useful to have several ways of communicating with the daemon - for example, occasional users might use a web site, more frequent users might have a command line interface.

Re: Security, root and CGI?
by ig (Vicar) on Jan 29, 2009 at 05:09 UTC

    You could use Kerberos to authenticate your CGI script to your runs-as-root script (and vice-versa if you wanted even more security).

    To avoid a secret being recorded in your CGI script or one of its configuration files, you could run the script in a persistent environment (e.g. mod_perl) and have an operator enter the secret on startup.

    It should be sufficient to authenticate the user once. Securing communications between your CGI script and your runs-as-root script is a separate problem from user authentication.

Re: Security, root and CGI?
by Krambambuli (Curate) on Jan 29, 2009 at 07:42 UTC
    Out of curiosity: have you maybe had a look on Webmin, to check if it would make sense to customize or add a plug-in that would do what you need ?



      My advice: If you want security then stay away from Webmin.

      Or atleast, that's my advice from looking at it a couple of years ago... it's implementation that is... I gave up trying to explain the security risk to the author... exploits that could be easily verfied (and fixed) were only met with a response: 'fixed in xyz' (testing xyz revealed it was not fix - so much for testing)

      Also: webmin runs everything as root. Only thing it takes is one little exploit in one of the module and you have root access. (And unless the code really changed in the past years then I'm sure there are many exploits in it)

Re: Security, root and CGI?
by skx (Parson) on Jan 29, 2009 at 22:35 UTC

    One way of promising that input comes from a particular user, (not script), is to have the communication be asynchronous.

    Have the CGI application run as user "foo" and create /var/spool/foo which is mode 700.

    The CGI script can validate and create jobs in this directory that the root process can examine, validate some more, and then process.

    Thats the cleanest separation I've ever used - in general I prefer to use sudo.

Re: Security, root and CGI?
by ruzam (Curate) on Jan 29, 2009 at 19:49 UTC

    I've had/have the same problem. I once hacked on an application that simply runs the CGI as suid and switches back and forth between root and a less privileged user as required. I suppose webmin might fall under that description. Sometimes it's difficult to setup on different systems, but for the most part it's simple and it works, provided you trust your CGI code and what it's doing. You can get a performance boost using Persistent Perl (Speedy CGI), but it also puts the application at odds with mod_perl so it could never run it under mod_perl.

    When started to build my own CGI applications I didn't want to mess with full suid run-as-root privileges so my approach to the problem was to create separate runs-as-root suid scripts that do small and defined tasks and leave the CGI scripts to run with what limited access they get from the web server. When the CGI needs to do a run-as-root operation, it executes the run-as-root script passing parameters in the command line, soaking up output from the run-as-root script as return data. One of the parameters passed, is the session id of the CGI script. If the run-as-root can't verify the session id, it simply returns without doing anything.

    Splitting the CGI and run-as-root sides into separate scripts offers a lot of flexibility (I think) for how you run the CGI side. But I don't think it's any more secure than a single suid CGI script doing it all. Ultimately, you still depend on the CGI side not doing something stupid with your run-as-root script. I like to think that there's some benefit to be gained by keeping the run-as-root code as small as possible so it's easier spot potential risks, but that's a warm fuzzy, and not necessarily a hard fact.

    So far I've only been working with defined functions (reading DHCP leases for instance) but in the distant future I also expect access file systems (user mail spools and home directories for example). When that time comes, I'll probably explore a daemon/socket approach.

    I've been thinking about this quite a bit. Send me a pm if you want to exchange some code and talk about it more!

Re: Security, root and CGI?
by papidave (Pilgrim) on Jan 30, 2009 at 12:58 UTC
    Sudo is a beautiful thing. But, like any powerful tool, it must be used wisely.

    I find it most useful to wrap specific tasks (in Perl, naturally) with taint-safe code that restricts what can be done. Then, you grant sudo access only to that script -- not the system utilities it invokes. Since you're running through a web server, sudo access must be granted to the account under which that web server runs, not the account under which the user has been authenticated.

    As far as authentication goes, I don't think you need to do it more than once -- if the user as originally authenticated had a role with additional privileges, he or she can do the advanced tasks. If not, access denied. That said, you might want to include a confirmation dialog for tasks that are somewhat risky -- like rebooting a production server.

Re: Security, root and CGI?
by jvector (Friar) on Jan 30, 2009 at 19:00 UTC
    If you can bear the time delay, IMO the solutions using an intermediate scratchpad (database, file) for communication look preferable to those involvong direct communication with authentication : less to risk getting wrong.

    This signature jvyy or ernql ol Puevfgznf
Re: Security, root and CGI?
by Fjdude (Initiate) on Jun 29, 2010 at 18:44 UTC
    I've done this... Http:// We use it a lot and it easy to extend with new functionality. Grtz Freddy

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2020-10-26 19:22 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (252 votes). Check out past polls.