httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Behlendorf <>
Subject Re: security holes and other fun stuff
Date Mon, 15 Jul 1996 06:41:31 GMT
On 15 Jul 1996, Dean Gaudet wrote:
> In article <>,
> Brian Behlendorf  <> wrote:
> >On 13 Jul 1996, Dean Gaudet wrote:
> >> While thinking on my VirtualHost syntax problem, and Cliff's request
> >> I think I've discovered several configuration-related security (and
> >> reliability) problems, one of which bypasses access controls.
> >> 
> >> First, a serious one.  Suppose the same webserver has an internal vhost,
> >> an external vhost, 
> >
> >(I'm presuming here you mean, two IP numbers, say X and Y?)
> Actually I've tried to exploit it now that I've had sleep, and
> I can.  Suppose that you have an ip-vhost, and
> that is the machine's physical address (i.e. the
> "main server address" in our documentation on vhosts), and doesn't
> appear in any <VirtualHost> statement.  Then sending a request with
> "Host:" or "GET HTTP/1.1"
> to the physical address will cause the webserver to serve data from
> instead of

As it should, in my opinion, and probably also in the opinion of other
server implementors on http-wg.  What it seems you object to is the
configurability of this presumption.  I would probably support the
creation of an obscure config directive like "No1.1VHostSupport" or
something to specifically disable this feature.

> Essentially what is happening right now is that a request can come into
> the "main" address(s) and can then be mapped to any vhost, regardless
> of whether that vhost is a name-vhost or an ip-vhost.  This violates
> the Principle of Least Astonishment I think.

I feel exactly the opposite, but I might be too "close" to the issue to
judge fairly.  

> You want a real world example of where this might be a problem?  Suppose
> you've created some forms-based mgmt software for your webserver, and
> suppose you don't trust Apache's access control (I don't -- I can get
> into this later -- but any good admin doesn't trust any access control and
> piles it all on).  Then a reasonable solution is to put that forms-based
> control stuff on addresses which the outside world "can't reach" (i.e. RFC
> 1597 private network addresses).  Of course if you're clued enough to
> make it that far you'd also slap password and group restrictions on it.
> But you'd still be astonished that suddenly your web server is happily
> "routing" stuff it shouldn't.

I can't believe that if you're clued enough to use private network
addresses, you wouldn't also know that vhosts can be requested via the
Host: header.

I support the idea of putting in the vhost documentation a warning
about this "gotcha".  I would also support the idea of describing a way to
do this using Listen and two separate pools of servers so that there's no
way that one could serve the tree from the other.  And as I said before,
as a last resort, I'd support an obscure directive turning off support
for the Host: header.  But I don't support changing the way the config
files work, for this purpose.

[Now on to a separate issue, which is denail of service attacks when the
DNS fails for a named vhost]

> >So, the policy here should be, if DNS names fail to resolve correctly to
> >an IP address on the machine, then that particular vhost setting fails
> >but the rest of the server comes up.
> Ahh but there's more than that happening here.  I'm talking about
> configuration gotchas... and I'm hoping that we'll amend the
> documentation.  Let me give an explicit example.
> Suppose is served from ISP.  Their competitor decides
> they want to steal web traffic.  So call up the ISP and ask for service
> for (competitor controls  ISP gives
> them an IP address and tells them how to configure things, blah blah.
> ISP's httpd.conf looks like this:
>     <VirtualHost>
>     blah blah
>     </VirtualHost>
>     ...
>     <VirtualHost>
>     blah blah
>     </VirtualHost>
> Now, competitor changes their DNS so that maps to
>'s address.  Take a boo at virtualhost_section() and
> you'll see that it places BEFORE in the
> virtual host searchlist.  Bingo, any hit to's address will
> be served out of the configuration.  

*Well*, any hit which doesn't contain the Host: header.  If everyone used
the Host: header, how would get a hit from

> The ISP probably
> won't notice ('cause of the thing Cliff reported and I said was hard to
> figure out in general with http/1.1 to consider).

This is another valid instance where a "No1.1VHostSupport" could be
used, so long as concern about supporting Host-less clients was important.
Secondly, I'd support making the chain created by virtualhost_section() go
in the opposite order - should be easy to do, no?  Hmm, perhaps we could
also have a "EnforceHTTP1.1" directive which rejects requests without a
full URI or Host: header.

> Sure, it won't last long.  But maybe it will... maybe the competitor is
> also smart enough to clone most of's site and only change a
> few important details... like where the credit card numbers are mailed.
> Some sites are changed so infrequently this charade might be easy to
> keep up for ages... may just figure "there's really no money
> in the net" as all their traffic is stolen by competitor.


> >I'd prefer the name the vhost responds to should be a union of the
> >ServerName and ServerAlias settings, not just ServerAlias.  Ugh, but then
> >you get things like
> >
> ><VirtualHost>
> >ServerName
> >....
> ></VirtualHost>
> >
> ><VirtualHost>
> >ServerName>
> >...
> ></VirtualHost>
> >
> >hmm... slight semantic change, I suppose.
> I'm moving in this direction... I'm thinking that we should have
> ip addresses which serve sets of vhosts (even in the name-vhost
> world there are cases when you'll want to spread them over several
> addresses).  Within each set HTTP/1.1 methods are used to determine
> which vhost to use.  The administrator should be able to statically
> control set membership.  We're almost there now if we use my suggestion
> of <VirtualHost A.B.C.D>+ServerName "" for all virtualhosts
> in the config... two things short:
> - can only do HTTP/1.1 stuff with the "main" server address

Eh?  I can do a telnet 80 and say "GET" and it works fine...

> - it doesn't respect "set" boundaries

I.e., if I make a request in set A for a host in set B... hmm, maybe that
magic directive should be "NoShareVHostsBetweenIPs" instead of

> But I think it's confusing...

Ya.  If only TimBL hadn't presumed there'd only be one server on port 80
per machine back when he was releasing HTTP.  But given his other
successes, I forgive him.  :)

> >> So... do we want to rethink the syntax?  At the moment it's actually a bad
> >> thing to be forced into name-vhost mode because not all clients support
> >> it.  In the future this may not be an issue.
> >
> >On the flip side, the current setup would allow ISP's who are currently
> >burning IP addresses with vhosts to allow those sites whose DNS is
> >controlled elsewhere to migrate without having to coordinate it with the
> >server authority; in other words, if I have a web site at using
> >, and best currently gives me an IP number but want it back,
> >then I can change the IP mapping of "" at any time to the
> >"centralized" vhost IP number, and I won't need to coordinate
> >that with best's sysadmins.  So, what to some people is a bug, is a
> >feature to others. :)
> Best needs to know about the change anyhow -- since they'll want to know
> that you've freed up the number.  It isn't hard for them to move your
> vhost to another spot in the config file.

But it requires exact timing (or at least, coordination of two events
within close proximity - adding a second entry to their config files for
you, and then after your switch removing your old entry).  Yes, eventually
I tell them the old IP address is gone, but only after I'm sure no one's
using it.

> >> - Apache doesn't do double reverse lookup for DNS based authentication.
> >
> >At least when I wrote about this for my book, I did mention that
> >host-based access control was unsafe unless used with MAXIMUM_DNS (time
> >to make this a runtime config?) or unless one used IP numbers.
> We should probably put this on the mod_access todo list:
>     - allow double reverse lookup to be configured only for those hits
> 	requiring it so that you don't have to suffer from MAXIMUM_DNS
> 	for every hit

Sure.  In fact, I would be comfortable with that as the default - any hit
which is protected by a non-numeric hostname is subject to reverse dns

>     - provide a global "IPAuthByNumberOnly" that will barf on any allow/deny
> 	that isn't numeric
> 	-- this is because some configs are built out of lots of small files
> 	    that are edited by less knowledgeable people and/or you use
> 	    .htaccess files
> 	-- the barf should be a warning and the result should be to deny
> 	    everything (a nice safe way to continue after the error in the
> 	    config file)


> >Wouldn't it be saner to just set it to the IP number?
> Actually, I like this approach:
> *** http_main.c.orig    Sun Jul 14 19:35:11 1996
> --- http_main.c Sun Jul 14 19:36:53 1996
> ***************
> *** 1058,1065 ****
>       /* Main host first */
> !     if (!s->server_hostname)
>         s->server_hostname = get_local_host(pconf);
>       def_hostname = s->server_hostname;
>       main = gethostbyname(def_hostname);
> --- 1058,1069 ----
>       /* Main host first */
> !     if (!s->server_hostname) {
> !       fprintf(stderr,"httpd: leaving ServerName unset is considered harmful to your
> !       fprintf(stderr,"httpd: but I'll let it slip for the moment, and attempt to use
> !       fprintf(stderr,"httpd: to find it... who knows what I'll do if your name server
is down.\n");
>         s->server_hostname = get_local_host(pconf);
> +     }
>       def_hostname = s->server_hostname;
>       main = gethostbyname(def_hostname);

What I'm suggesting is that if get_local_host fails, just use the IP
number as the ServerName.  I guess in addition to this, sure.

> Maybe I should just write a page "DNS Considered Harmful" and get you
> guys to link to it from the docs? :)
> Seriously... I have to get in there and dig around in order to implement
> my multi-ip vhost stuff.  Is there a better way we should do it?

As you've probably seen, I would prefer to go with the status quo, and
offer configuration directives for what I feel will be seldom-needed
restrictions on functionality.

> I figure I got no comments on my previous post about multi-ip syntax (i.e.
> <VirtualHost> responding to both addresses) because:
>     (a) everyone liked it (or didn't care)
>     (b) I didn't include a patch and everyone was waiting for the patch
> 	to show up before arguing about how it should be done.
> My experience with this list says (b) is the answer :)

Actually, I thought I remember some favorable comments... certainly, a
lack of negative comments does mean something good, but you need to at
least convince someone to commit it  :)  

> I see two ways to approach vhost mapping.  One is to define the mapping
> when the vhost is defined, and the other is to define all the mappings
> together and have them symbolically refer to vhosts.  The first is great
> for newbie admins because it does a lot of stuff implicitly (i.e. creates
> name-vhosts without telling you).  The second is great for the person
> writing the mapping code because it abstracts the mapping out of the
> server_rec structure (which is a Good Thing).  Consider:
>     # syntax <VirualHost SYMBOLIC-VHOST-NAME>
>     <VirtualHost vhost1>
>     ServerName
>     # other goo blah blah
>     </VirtualHost>
>     <VirtualHost vhost2>
>     ServerName
>     # other goo blah blah
>     </VirtualHost>
>     ... and so on up to 4
>     <VirtualHost go-away-server>
>     ServerName
>     # a server which sends back "go away" for any request
>     </VirtualHost>
>     # We now map ip addresses to symbolic-vhost-names.
>     # Syntax: <Map ip-address*> ... </Map>
>     # Ordering within a Map is important.  Ordering of Map statements isn't,
>     # Map addresses can't overlap (we want to move towards hashing at least
>     # ips).  If you want to use DNS names in map statements then you have
>     # to define SHOOT_FOOT when compiling the server.
>     <Map>
>     MatchHost vhost1
>     MatchHost vhost2 *
>     MatchPath vhost1 /vhost1 /alpha
>     MatchPath vhost2 /vhost2
>     #
>     Default vhost1
>     </Map>
>     # and now a mapping for another address, this is an ip-vhost only
>     <Map>
>     Default vhost3
>     </Map>
>     # this one responds on multiple addresses
>     <Map>
>     Default vhost4
>     </Map>
>     # and this one responds to any ip not present in the other rules
>     <Map>
>     Default go-away-server
>     </Map>
>     # an alternate option is to return 403 for anything that isn't matched
>     # by a map...
> Notice that this way it's easy to see all the aliases and path mappings
> for a particular ip.  It'd also be possible to do some easy optimizations
> such as turning a sequence of "simple" MatchHost statements (those
> without wildcards) into a hashtable (a big win later on as name-vhosts
> become common and every ISP is happily giving them out).

Hmm... personally, I'm not convinced.  The above is not necessarily more
readable or intuitive or less error-prone than the existing config files -
that's for me, and I admit I may be biased by being too close to the
problem.  I won't even mention the political cost of asking people to
totally change config files.  And while us computer scientists like adding
layers of indirection, it might be somewhat confusing for the average
webmaster. :)

Question: why can't hash tables be used for existing config files for
non-wildcard vhosts?



View raw message