Is there a security risk in running a web server like Unicorn as root?
As Thomas said in sec.se chat, running anything as root carries an implicit security risk. The thing to understand about root is that the kernel essentially trusts all its actions without complaint.
The issue occurs if there are any vulnerabilities in nginx, or unicorn. If this happens, it may be possible to execute an exploit, misusing the process.
However it is important to understand how these servers work to understand what the exploit vector may be. In theory, there are two parts that must occur holding root permissions - the reading of configuration and the
bind() operation, assuming your server has a port < 1023.
unicorn acts (assuming gunicorn is similar) as a prefork model - each client request is handled in a separate process. The job of the process running as root is to bind to the necessary port and then pass connections off to the workers. Worker models mix threads and processes. As I understand it nginx operates in a very similar way, with the proviso that it has a greater bias to asynchronous IO - I believe
accept. If you have a look at the strategies for solving the c10k problem these are why the designs operate this way.
In theory, then, most worker processes can
seteguid() to drop their root permissions and should do so. Problems arise when these processes do not and handle all their traffic as root; most processes do drop their root permissions. I should also make two fairly obvious statements:
- You could configure your nginx daemon to run as something other than root if you do not bind to ports < 1024.
- You can (and I do) configure unicorn (gunicorn) in my case to create socket files, meaning it does not need to be run as root. nginx can proxy web requests onto unix sockets, meaning gunicorn never exposes a tcp connection.
The "vulnerable section" of code should therefore amount to parsing the config file and handing off connections; in theory the danger to root is therefore quite minimal assuming this works and is heavily tested.
POSIX capabilities are a different way (other than setuid bits) to delegate portions of root's capabilities to other processes;
CAP_NET_BIND_SERVICE for example allows a process to bind to a port less than 1024 without having to be root. They work via extended attributes I believe. Fedora has recently (f16?) moved to ensuring all packages use capabilities rather than sticky bits.
Another point of note and hopefully a positive one - unicorn, if I understand it correctly, is a ruby process (gunicorn is definitely a python process). The use of an interpreted language does reduce the risk that the developers have introduced bugs as the string handling should definitely be safe and pointers are not available. However, bugs with the interpreter may cause a security risk to all interpreted programs, too.
The unfortunate reality, however, is that a compromise of your
www-data process is still going to be a problem for you; an attacker can potentially dump your database, deface your website etc. Knowing root is secure is great, but if for example your website is your main advertising point for your customers, having it defaced is still a threat to your business.
Yes, running unicorn as root is a risk. However, the attack surface is relatively small in terms of the code that will execute as root. Also, there may be options for minimising what you run as root. I have also not covered MAC systems such as SELinux, but these are viable options along with capabilities assuming you're prepared to learn them. The important thing to understand is that risk is a balance - how sensitive/important this service is will determine how much effort you should put into securing it. If you're running a banking website, you might want to think seriously about how you harden your system; if this is a website hosting lolcat pictures (ok, y'know what I mean) you may decide the current setup is just fine.