Running network services as a non-root user.

Posted by Steve on Wed 19 Apr 2006 at 07:48

There are many times when it is convenient to allow non-root users to run services, or daemons, which bind to "privileged ports". There are several approaches to this problem each with its own set of pros and cons. Read on for a brief look at the most common approaches.

A common task is to allow a user to run a Webserver, or other process, which needs to listen upon a network socket which is privileged. Traditionally only the root user is allowed to bind() to a port with a number lower than 1024. There are many services which require root privileges specifically for binding to a low-numbered port, rather than anything else. Are you sure you trust them to drop privileges after setting up the listening socket..?

There are some kernel patches which will allow different security models to be used, these may allow local users who are members of a special group to bind to a low port - however using these patches is quite a lot of effort.

The simpler alternatives include the following:

  • Using a firewall to redirect packets.
  • Using authbind.
  • Using sudo.
Using a firewall to redirect packets

Essentially you'll tell your user to bind their server to a port which they do have permission to use - anything over 1024 should be fine. In our example we'll use tell our user to setup their webserver to use port 2080. then add the following iptables rule to our firewall script:

# Redirect *:2080 -> *:80
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 2080

This rule will allow incoming connections to the standard HTTP port (80) to be seamlessly redirected to port 2080; the port the user is actually using.

If you're not using a firewall right now simply create the file /etc/network/if-up.d/firewall (make it executable) and give it the following contents:

#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin

# Flush any existing firewall rules we might have
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X

# Perform the rewriting magic.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 2080
Using authbind

The authbind package is designed to allow users to bind servers upon a low-numbered port. The package may be easily installed upon Debian systems by executing:

root@lappy:# apt-get install authbind
..
..

Once installed the software is configured via files located beneath /etc/authbind. There are three subdirectories:

  • /etc/authbind/byport
  • /etc/authbind/byuid
  • /etc/authbind/byaddr

The manpage to the authbind program explains how these subdirectories are used. But as a simple example we can allow the user skx to bind to port 80 by running the following commands:

root@lappy:~# touch /etc/authbind/byport/80
root@lappy:~# chown skx:skx /etc/authbind/byport/80
root@lappy:~# chmod 755 /etc/authbind/byport/80

Here we have created a file with the name 80 (which is used to specify that the user may bind to port 80). This file is executable to the user skx - this is sufficient for the user to bind to port 80 - if they prefix their command with authbind.

For example the skx user could run something like the following:

skx@lappy:~$ authbind nc -l -p 80 -e "/usr/bin/uptime"

(This listens for incoming connections on port 80 and sends the output of the uptime command to connecting clients. It is the simplest test of binding a socket I could think of! The netcat utility has been introduced previously.)

Using sudo

Using the sudo package it is possible to delegate privileges to local users in a controlled manner.

If you wish to allow a user to execute a daemon you might be able to simply grant them permission to execute the startup file for it. For example the following snippet from /etc/sudoers allows the user skx to restart the Apache2 server:


# User alias specification
User_Alias      FULLTIMERS = skx

# Cmnd alias specification
Cmnd_Alias      APACHE=/etc/init.d/apache2

# full time sysadmins can restart Apache:
FULLTIMERS      ALL = NOPASSWD: APACHE

However this solution does have a problem: Whilst the given user can start and stop the service they cannot edit the configuration file(s):

skx@lappy:~$ sudo /etc/init.d/apache2 reload
Reloading web server config...done.

To handle this case you could use a server-specific setting - such as adding the following to /etc/apache2/apache2.conf :

Include /home/skx/apache2/server.conf

This may or may not cause even more problems. It really depends upon the server, and how liable you think they are to try to leverage their elevated privileges to a root compromise ...

sudo is an exellant utility in most regards, but this is a situation where I think it is less useful than usual.

 

 


Posted by chris (217.8.xx.xx) on Wed 19 Apr 2006 at 12:38
[ View Weblogs ]
I can't see that the problem with sudo is solved easily for the other two. With authbind and firewall you still can't edit the config files?

Of course - with those two you can have a local install of the app in your home directory - but you could have that with sudo too.

[ Parent | Reply to this comment ]

Posted by Steve (212.20.xx.xx) on Wed 19 Apr 2006 at 12:41
[ View Steve's Scratchpad | View Weblogs ]

The assumption is that if you're using sudo you're giving control of the system installation of a service - such as Apache.

Whereas if you're using an authbind, or iptables, solution it is more natural to have a local copy the user has in their own home directory - since they still need to edit configuration files, etc.

I guess you could use any solution in either approach though. That is just the way I was thinking about it.

Steve

[ Parent | Reply to this comment ]

Posted by simonw (84.45.xx.xx) on Wed 19 Apr 2006 at 21:36
[ View Weblogs ]
Steve,

perhaps you can answer a question I've long had, "why don't we fix the kernel for this?".

I've read the relevant code, it basically says "if port less than 1024 then check calling process uid is 0", and it would appear simple to me to change the check such that the calling process has the same uid as a user defined in "/etc/service_owner".

21:vsftp
25:mail-listener
80:www-data


Then there would be no need for a root privilege to bind to ports below 1024, and great swathes of weird solutions, and whole classes of root exploit would "just die".

This always struck me as application programmers working around a broken design, but maybe I'm being naive?

[ Parent | Reply to this comment ]

Posted by Anonymous (65.211.xx.xx) on Fri 21 Apr 2006 at 16:21
I've never used it but it looks like this patch could do that job.

http://www.olafdietsche.de/linux/accessfs/

It creates a virtual fs to represent ports which you then chown to whatever user you want to be able to bind the port. I wish I had a spare machine lying around right now to try it on.

[ Parent | Reply to this comment ]

Posted by sytoka (83.177.xx.xx) on Sat 22 Apr 2006 at 07:44
And I do not understand why all Apache process run under www-data identity ! It is really very dangerous. Why it is not possible to run each virtual host under a different identity.

I know, I can run virtual machine with Xen but it's not a good solution. I just want want to have each virtual host web server run with a different identity to secure and separate the server.

[ Parent | Reply to this comment ]

Posted by simonw (84.45.xx.xx) on Sat 22 Apr 2006 at 12:12
[ View Weblogs ]
You can it is called the "suexec security model", and Apache defaults to not using it for security reasons.

http://httpd.apache.org/docs/2.0/suexec.html

In most cases ISPs make the owner of the files Apache serves a specific user, and just gives www-data read permission, in such circumstances the dangers aren't huge, and mostly revolve around what else you let Apache trust users for (htaccess files, Overrides, and ModPerl etc), and dynamic content.

Where we've seen compromises with Apache webhosting it is usually followed by loading stuff to "tmp", and a root privilege elevation (or failed attempts at same), as exploiting the ownership of the www-data process is difficult and complex (or at least highly variable) to exploit. Where as with root or another user account it is easy to do abusive things - load up CGI scripts for sending email or phishing etc.

i.e. the first thing all the successful exploits have done, is to find an escape from the security model you think is broken.

Probably the biggest problem is the number of slightly iffy apps, whose install instructions think "chmod 777" is the solution to security constraints, but I think that isn't Apaches fault, and I haven't seen that many problems as a result as Apache doesn't have a "write to a file I can write to" action by default, that is always added in later (WebDAV, PHP, Perl etc).

Sure there is a problem with a customer trying to attack another customers site, but even here proper permissions mean this is limited in scope to files with the wrong permissions, and in most cases you have contracts, and agreements with customers. Most of the bad guys are not your paying customers.

[ Parent | Reply to this comment ]

Posted by Anonymous (193.62.xx.xx) on Fri 12 Dec 2008 at 16:39
"allows the user skx to restart the Apache2 server"

Looks like it's the user "steve".

[ Parent | Reply to this comment ]

Posted by Steve (89.16.xx.xx) on Fri 12 Dec 2008 at 16:41
[ View Steve's Scratchpad | View Weblogs ]

Good catch. I've updated it now.

Steve

[ Parent | Reply to this comment ]

Posted by Xan (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Fri 19 Feb 2010 at 07:16
Don't the file permissions in your authbind example give everybody the ability to bind to the port? Shouldn't they be, for example, 750 rather than 755?

[ Parent | Reply to this comment ]

Posted by Anonymous (217.72.xx.xx) on Mon 8 Aug 2011 at 12:57
If you want to redirect packages locally, add this line too:

iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-port 2080

The OUTPUT chain checks for locally created packages.

[ Parent | Reply to this comment ]

Sign In

Username:

Password:

[Register|Advanced]

 

Flattr

 

Current Poll

What do you use for configuration management?








( 524 votes ~ 7 comments )