2

Someone has managed to pass an undefined HTTP_HOST server variable to my application script, triggering a series of errors. I am quite perturbed but am unable to replicate this behaviour. My httpd server uses name-based virtual hosting with the following parameters:

ServerName example.com:80
UseCanonicalName On

<VirtualHost *:80>
  ServerName example.com
  ServerAlias ftp.example.com service.example.com
  ErrorDocument 404 /error/404.html.var
...
</VirtualHost>

<VirtualHost *:80>
  ServerName notfound.example.com
  ServerAlias *
  RedirectMatch 404 ^/(?!error)
  ErrorDocument 404 /error/404.html.var
</VirtualHost>

I tried to replicate the request using wget with the following:

wget -dS --header='Host: ' http://example.com/?x0a/x04/x0a/x04/x06/x08/x09/...
--2014-07-30 03:00:00--  http://example.com/?x0a/x04/x0a/x04/x06/x08/x09/...
Connecting to example.com:80... connected.
---request begin---
GET / HTTP/1.1
Accept: */*
Host: 
Connection: Keep-Alive

---request end---
...
HTTP request sent, awaiting response... 
---response begin--
  HTTP/1.1 404 Not Found
  Date: Wed, 29 Jul 2014 03:00:00 GMT
  Server: Apache
  Accept-Ranges: bytes
  Keep-Alive: timeout=5, max=100
  Connection: Keep-Alive
  Transfer-Encoding: chunked
  Content-Type: text/html; charset=UTF-8
  Content-Language: en
---response end---
...
2014-07-29 03:00:00 ERROR 404: Not Found.

And as expectedly, a 404 not found error is delivered. I wonder how anyone can trigger a 200 success with an undefined HTTP_HOST. Does ServerAlias in Apache rely on HTTP_HOST at all? Or could this be a server bug that someone is trying to exploit?

UPDATE:

This is the output from httpd -S:

VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server example.com (/etc/httpd/conf/httpd.conf:410)
         port 80 namevhost example.com (/etc/httpd/conf/httpd.conf:410)
                 alias localhost
                 alias xxx.xxx.xxx.xxx
                 alias ftp.example.com
                 alias service.example.com
         port 80 namevhost notfound.example.com (/etc/httpd/conf/httpd.conf:491)
                 wild alias *
ServerRoot: "/etc/httpd"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/etc/httpd/logs/error_log"
Mutex default: dir="/run/httpd/" mechanism=default 
Mutex rewrite-map: using_defaults
Mutex ssl-stapling: using_defaults
Mutex proxy: using_defaults
Mutex ssl-cache: using_defaults
PidFile: "/run/httpd/httpd.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="apache" id=48 not_used
Group: name="apache" id=48 not_used
Question Overflow
  • 2,103
  • 7
  • 30
  • 45
  • 2
    Maybe this is relevant: "The first vhost in the config file with the specified IP address has the highest priority and catches any request to an unknown server name, **or a request without a Host: header field (such as a HTTP/1.0 request).**" My emphasis on the latter disjunct, which is distinct from a `Host:` header with an empty host. (Just a comment because I'm too lazy to test this.) – Mark Wagner Jul 30 '14 at 03:46
  • @MarkWagner Could you write that up as an answer? Thank you! – Chris S Jul 30 '14 at 04:08

1 Answers1

1

Yes, ServerAlias works exactly with the HTTP_HOST variable (more correctly, with the Host: http header of the request, which will be mapped to HTTP_HOST as well).

If there is no Host: http header, AND the request_uri contains a http host as well (i.e. GET http://example.com/path/to HTTP/1.1), it will be also used as HTTP_HOST. This happens normally in the case of proxies only.

Your example is bad, Host: can't contain an url, only a host name. If somebody gives here an url (probably by a bad http tool), it will be interpreted as an invalid/nonexistent host name, and this is what in your case happens.

Practically: Although I we could find and analyze the relevant parts of the (public) source code of the apache webserver, I don't think such hard things are needed. The best what you can do is to play with your own apache with some telnet 127.0.0.1 80 or similar commands. Give different GET /url, Host: headers to your virtualhosted apache and see, what happens. This is what I did with a lot of times when I needed to debug virtualhosted apache configurations. A telnet-based http query minimalexample is here:

$ telnet 127.0.0.1 80
GET /test/url.html HTTP/1.1
Host: myapache.mydomain.com
Connection: close

(me: until this you need to type in, don't forget the multiple enter at the end)
200 HTTP/1.1 OK (<- me: from here is coming the reply of the server!)
Content-type: html/html

<html> 
...
</html>
peterh
  • 4,953
  • 13
  • 30
  • 44
  • Thank you. Do you have any references to support your statement in the first paragraph? I tried but can't find it on the manual. And for the `wget` example, how do I send a `HTTP/1.0` request without `Host:` being defined? – Question Overflow Jul 30 '14 at 06:42
  • @QuestionOverflow Yes, but not a link, but a try. Although I could find the relevant parts in the (public) source code of the apache webserver, I don't think such hard things are needed. The best what you can do is to play with _your_ own apache with some telnet 127.0.0.1 80 commands and giving different GET /url, Host: headers to your virtualhosted apache and see, what happens. This is what I did with a lot of times when I needed to debug virtualhosted apache configurations. I extend my answer with that. – peterh Jul 30 '14 at 06:50
  • Thank you! I guess I will have to install telnet then. :) – Question Overflow Jul 30 '14 at 07:07
  • You cannot specify the HTTP version with `wget`. You can with `curl`, however (the `--http1.0` option). – Mark Wagner Aug 06 '14 at 18:00