Watch out for web server configurations that 'cross over' between sites

October 14, 2016

We have a long-standing departmental web server that dates back to the days when it wasn't obvious that the web was going to be a big thing. Naturally, one of the things that it has is old-style user home pages, in the classical old Apache UserDir style using /~<user>/ URLs. Some of these are plain HTML pages in directories, some reverse proxy to user run web servers, and some have suexec CGIs. The same physical server and Apache install also hosts a number of other virtual hosts, some for users and some for us, such as our support site.

Recently we noticed a configuration problem: UserDirs were active on all of the sites hosted by Apache, not just our main site. Well, they were partially active. On all of the other virtual hosts, you only got the bare files for a /~<user>/ URL; CGIs didn't run (instead you got the contents of the CGI file itself) and no reverse proxies were in effect. We had what I'll call a 'crossover' configuration setting, where something that was supposed to apply only to a single virtual host had leaked over into others.

Such crossover configuration leaks are unfortunately not that hard to wind up with in Apache, and I think I've managed to do this in Lighttpd as well. Generally this happens when you set up some configuration item without being careful to explicitly scope it; that's what Ubuntu's /etc/apache2/mods-available/userdir.conf configuration file did (and does), as it has the following settings:

<IfModule mod_userdir.c>
  UserDir public_html
  UserDir disabled root
  [...]
</IfModule>

(This is actually a tough problem without very split apart configuration files. Presumably Ubuntu wants a2enmod userdir to automatically enable userdirs in at least your default site, not just simply turn the module on and require you to add explicit UserDir settings to things.)

In Lighttpd you can get this if you put any number of things outside a carefully set up host-specific stanza:

$HTTP["host"] == "..." {
   # everything had better be here
}
# oops:
alias.url += ( "/some" => "/fs/thing" )

And it's not like a web server necessarily wants to absolutely forbid global settings. For instance, in my Lighttpd setup I have the following general stanza:

# Everyone shares the same Acme/Let's Encrypt
# challenge area for convenience.
alias.url += ( "/.well-known/acme-challenge/" => "/var/run/acme/acme-challenge/" )

This is quite handy, because it means the tool I use needs no website-specific configuration; regardless of what website name it's trying to verify, it can just stick files in /var/run/acme/acme-challenge. And that makes it trivial to get a LE certificate for another name, which definitely encourages me to do so.

I do wish that web servers at least made it harder to do this sort of 'crossover' global setting by accident. Perhaps web servers should require you to explicitly label configuration settings with their scope, even if it's global. You might still do it, but at least it would be clearer that you're setting something that will affect all sites you serve.

(In the mean time, I guess I have another rainy day project. I have to admit that 'audit all global Apache configuration settings' is not too thrilling or compelling, so it may be quite some time before it gets done. If ever.)

Written on 14 October 2016.
« How I've set up SSH keys on my Yubikey 4 (so far)
ZFS's 'panic on on-disk corruption' behavior is a serious flaw »

Page tools: View Source.
Search:
Login: Password:

Last modified: Fri Oct 14 02:10:38 2016
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.