http://www.perlmonks.org?node_id=740003


in reply to Security, root and CGI?

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!