I'm writing a program (in Python) that needs to modify a system file, /etc/aliases in this case. The software is a web application that typically will run under a dedicated web user, ie "www", "www-data", "apache" or similar.
How should I set up access control (file permissions, file ownership and groups) to enable the program to modify /etc/aliases without opening permissions too much?
The easy way is to make
/etc/aliases
owned by the web user. There are several ways you can make this more secure; it's a matter of what threats you're concerned about and how much complexity you're prepared to add to mitigate them.If the application is only supposed to modify some aliases, you might be able to set up your MTA to read several alias files, and make only one of them writable by your application. I don't think this will buy you much security against a security hole in the application: if an attacker adds a redirection from
webmaster
to[email protected]
, it doesn't matter which file it's been added to. But this could be useful in combination with review mechanisms.If you want to review or audit what the application is doing, don't give it write access to
/etc/aliases
. Instead, make it write a temporary file somewhere, then invoke a privileged program to validate this file and merge the data into/etc/aliases
(or a dedicated file as suggested above). The privileged program, let's call itmerge-myapp-aliases
, should be executable by the web user, and setgid to a dedicated group. That is,merge-myapp-aliases
should be owned byroot:myapp-aliases
and mode 2755 (rwxr-sr-x
). The reason to use a group rather than a user is that even if there's a security hole in the executable, the attacker won't be able to modify the executable to inject a trojan. The job ofmerge-myapp-aliases
is to validate the contents of its input (e.g. check that it's not setting aliases for system users), log its actions, and replace the alias file by a new version.For robustnes, the dedicated alias file should be in a dedicated directory with group write permission. Make the program write the new file (
/etc/aliases.myapp/new
), then atomically move it in place (mv /etc/aliases.myapp/new /etc/aliases.myapp/current
). That way you won't end up with an incomplete file if the program is killed midway for whatever reason.An alternate way of pushing the changes into place, which has the advantage of automatically leaving a complete audit trail, is to have the CGI commit a file to a revision control system, and pull a trigger for another program to check out the latest revision. Most revision control systems have a way to validate commits.
If you want to restrict the alias file to this particular application, you're going to have to run the application with elevated privileges somehow. As above, you can make it setgid to a dedicated group.
You don't say what MTS you are using. But this information is quite important.
/etc/aliases
is considered a Sendmail compatibility mechanism by several MTS softwares, whose native aliasing mechanisms are more powerful, and address the very security issues that you are hitting here. For examples:fastforward
add-on handles/etc/aliases
by plugging it into qmail's native aliasing system. The native aliasing system,.qmail
files, allows any local user[email protected]
to have a per-user set of aliasesfred-something@example.com
defined by.qmail-something
files in that user's home directory. The user doesn't need access to global root-owned files, and there's no way forfred
's alias files to alter whatjim-something@example.com
andsheila-something@example.com
map to.recipient_delimiter
option to gain a similar mechanism, withfred+something@example.com
aliases defined by.forward+something
files in that user's home directory.local_part_suffix
option can be turned on, and$local_part_suffix
will be set to-something
whenever the~fred/.forward
filter is run for mail addressed tofred-something@example.com
.The upshot of all this is that if your MTS is qmail, Postfix, or exim your WWW application just needs one unprivileged local user account in order to gain control over a whole set of mailboxes, and does not need either access to the system-wide alias database or any set-UID/set-GID shenanighans. For many tasks — running mailing lists, for example, that needs mailboxes named
list-subscribe
,list-owner
,list-unsubscribe
,list-handle-bounce-from-mandy-example.net-of-message-437
, and so forth — this is enough.Depending from what your application is, it might be enough for you, too.