You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dean Gaudet <dg...@hotwired.com> on 1996/07/13 09:47:22 UTC

security holes and other fun stuff

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, and access to the internal vhost is restricted
only by ip filtering (this is not unreasonable -- consider the use of
private network numbers).  We now parse HTTP/1.1 requests using either
"http://blah.com/asdf" URIs or Host: headers.  If you send a request to
the public address with a URI or Host: header pointing at the private
address the server will serve up the page.  I'm zoned at the moment,
so someone else should follow the flow through read_request() and into
read_request_line() and then into check_hostalias().  If I'm right,
we've got a problem.

Now on to some more mundane concerns.  Let "name-vhosts" refer to HTTP/1.1
virtual hosts, and "ip-vhosts" refer to ip-based virtual hosts.

Remember while reading this that it's common for ISPs to *not* be primary
for some customers' DNS, while at the same time hosting websites for
such customers.  Also remember that our docs all suggest the use of DNS
names instead of IPs when configuring either name-vhosts or ip-vhosts.

There are several reliability/denial-of-service possibilities involving
the use of DNS names in <VirtualHost> statements.  If name-vhosts (or
ip-vhosts) are configured in the manner described in the documentation
(i.e. using DNS names) then the server won't boot if DNS isn't working.
Furthermore, if any of the names used are in uncontrolled domains (i.e.
secondary or no local authority) then a third party can cause denial
of service.

Another possibility involving uncontrolled DNS:

    <VirtualHost abc.com>
    ...
    </VirtualHost>

    <VirtualHost def.com>
    ...
    </VirtualHost>

Suppose abc.com is your "main server address" and maps to 10.1.1.1 and
you expect def.com to map to 10.1.1.2, but you don't control def.com.
Then the def.com controller (or Evil Person) can force you to use
name-vhosts just by mapping def.com to 10.1.1.1.

Essentially, using DNS names in <VirtualHost> statements should be
entirely avoided.  This is true in pre-apache-1.1 syntax as well, since
def.com could force denial of service for abc.com if their ip addresses
match and def.com appears first (last?) in the config file.

Fortunately, I think we already have workarounds for all of the above.
Always use ip addresses and ServerName, even when defining a name-vhost.
For name-vhosts use ServerAlias to define the name your server responds
to.

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.

The documentation should be updated to at least mention this concern,
and maybe some other DNS concerns:

- Apache doesn't do double reverse lookup for DNS based authentication.
    There's even a helpful example of how to do it wrong in the
    access.conf-dist file for the status handler... which an "attacker"
    can easily spoof by playing with their reverse map.  Naive users
    (heck even HotWired's config had this problem when I arrived :)
    will fall into this trap.

    (I know there's the mention of MAXIMUM_DNS in the Configuration file.)

- If ServerName isn't set, apache does a reverse lookup in
    default_server_hostnames to find it.  If DNS is down when the
    server boots this will cause ServerName to be defaulted incorrectly.

    Actually, default_server_hostnames will segfault if somewhere
    between get_local_host and "main = gethostbyname..." there is a DNS
    failure... or if the servername is bogus.  patch:

*** http_main.c.orig    Sat Jul 13 00:02:03 1996
--- http_main.c Sat Jul 13 00:03:29 1996
***************
*** 1063,1068 ****
--- 1063,1074 ----

      def_hostname = s->server_hostname;
      main = gethostbyname(def_hostname);
+     if( main == NULL ) {
+         fprintf(stderr,"httpd: cannot resolve main ServerName.\n");
+         exit(1);
+     }
+

      /* Then virtual hosts */


Dean

P.S. People doing SSL for apache 1.1 should watch out for the "http://"
comparisons in check_hostalias().

P.P.S.  Hostnames such as "123.hotwired.com" are valid, yet find_allowdeny
does not properly handle them.  This should be put on Known Bugs.  Be
careful when fixing this because just removing the isalpha() check creates
a security hole, consider the DNS map "1.1.1.1.in-addr.arpa IN PTR 2.2.2."
if the user has a config line "allow from 2.2.2" it will allow 1.1.1.1 in
(unless -DMAXIMUM_DNS).  -- which is bad because it breaks people who
understand double reverse lookup and are trying to avoid it by using
only ip addresses on allow/deny statements.

P.P.P.S.  A response to the original article I was following up on:

In article <ho...@bauhaus.organic.com>,
Cliff Skolnick  <ne...@hyperreal.org> wrote:
>In your vitual host fixup, can you do one of the following:
>
>If a second virtual host directive is givin for an existing defined
>virtual host, then:
>
>1) A warning that the first directive's information is lost is
>output to the error log and/or stderr.
>
>2) The new values are merged into the existing virtual host.

I think I'd rather see a warning... I'm not sure why merging would
be useful -- unless you want to be able to define a virtualhost piecemeal,
a bit here, a bit there spread all over the config file(s).

It's also a pain in the butt to solve considering you have to compare
all possible methods of accessing each virtual server to even find it.
Sure, pure ip comparison would have been easy... but now with ServerAlias
and name-vhosts it's not fun.