Follow up question of How to exploit HTTP header XSS vulnerability?
Let's say that a page is just printing the value of the HTTP 'Host' header with no escaping. So the page is vulnerable to an XSS attack, i.e. an attacker can craft a GET request with a 'Host' header containing something like alert('xss');.
But how can you actually use this to attack a target? How can the attacker make the target issue that specific request with that specific header?
The http Host header is basically use as a string to figure out which of (potentially many) named-based hosts in the server configuration should be used to serve up the request.
Let's say you forged up an HTTP request and got this header sent over:
Host: <script>alert('foo');</script>.example.com
The ONLY way this could get through to the PHP script you want to attack is if the webmaster configured the server and site definition to allow that explicit hostname, or has wildcard naming in place, e.g.
<VirtualHost ...
ServerName www.example.com
ServerAlias *.example.com
</VirtualHost>
Since the wildcard allows ANYTHING before .example.com, your JS-hostname would get through.
But a vhost configured like this:
<Virtualhost ...>
Servername www.example.com
ServerAlias web.example.com
</Virtualhost
would not be vulnerable, because the Host name you've provided is not matched by ANY of the configured hostnames. The request may be handled by some other catch-all vhost, but since your vulnerable script doesn't exist on that site, that's useless to you.
Related
I'm currently writing a proxy server in nodejs. To proceed, I need to know how to reliably determine the originally intended domain of the client. When a client is configured to use a proxy, is there a universal way that the client sends this information (e.g. one of the two examples below), or is it application specific (e.g. Chrome proxy settings may do it differently to IE proxy settings, which may be different to a configuration for a proxy for an entire Windows machine, etc.)?
An HTTP request to the proxy server could look something like this, which would suffice:
GET /something HTTP/1.1
Host: example.com
...
In this case, the proxy could get the hostname from the 'Host' header, get the path in the first line of the HTTP request, and then have sufficient information.
It could also look something like this, which would suffice:
GET http://example.com/something HTTP/1.1
...
with a FQDN in the URL, in which case the proxy could just retrieve the path of the HTTP request in the first line.
Any information regarding this would be greatly appreciated! Thanks in advance for the help!
Apache has something called VirtualHosts.
You can configure it in that way that when you go to example.com get a different site than example2.com even if you use the same IP's.
A HTTP Request looks something like this:
GET /index.html HTTP/1.0
[some more]
How does the server know you are trying to access www.example.com or www.example2.com?
In addition to the GET line, the browser sends a number of headers. One of these headers is the Host header, which specifies which host the request is targeted at.
A simple example request could be:
GET /index.html HTTP/1.0
Host: example.com
This indicates that the browser wants whatever is at http://example.com/index.html, and not what is at http://example2.com/index.html.
Further information:
The Host header in the HTTP specification
IIS also has this and I believe refers to it as host header redirection.
The http packet header contains the destination hostname which the server uses to determine which website to serve up. Some more reading: http://www.it-notebook.org/iis/article/understanding_host_headers.htm
I'm trying to get the following done:
A HTTP request comes into an address subdomain.domain.com to a public ip on a machine running a proxy (maybe apache? Anything better?)
Based on the subdomain, I'd like the request to be redirected to an internal machine on a private ip, and specific port. The response for that request will come from that internal machine.
What are my options? Any general guidelines out there for achieving this? Whats a good proxy implementation choice? Will also need to dynamically add subdomains over time, which redirect to specific internal ips/ports.
How do ssl certificates work in a setup with subdomains? Is a separate certificate required for every subdomain?
The setup isn't too hard. You just make a virtual host for each subdomain and configure the vhosts as proxies. The approach is the same regardless of which proxy software you choose. I recommend you to use Nginx as an reverse proxy since the configuration is easier and the performance is much better than Apache. If you still want to use Apache, make sure you do not run PHP on the proxy machine and use mpm_worker instead of mpm_prefork.
You can make a script which adds new subdomains to the configuration file. It shouldn't be too hard since they will look almost the same, except for the path to the SSL certificate and the IP of the backbone server.
For SSL you can use a wildcard certificate which will cover the entire domain, including subdomains. This is not supported on all platforms, but the support have grown in the last years so it should be pretty safe.
Otherwise, without a wildcard certificate, you will need a certificate and a separate IP address per subdomain (since the SSL connection is set up before the domain name is known, you will need to differentiate different certificates by different IPs).
Apache is perfectly reasonable for this problem. You can do virtual hosts which use mod_proxy:
<VirtualHost *:80>
ServerAdmin xxx#yyy.com
ServerName foo.yyy.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyErrorOverride On
ProxyPass / http://192.168.1.1/
ProxyPassReverse / http://192.168.1.1/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
If you were looking to host hundreds or thousands of sub-domains you could actually do this with mod_rewrite instead, with a trick involving local name lookups that allowed you to proxy bar.yyy.com to something like local.bar.yyy.com. Using mod_rewrite for mass virtual hosting is mentioned in the apache docs, using it to proxy instead of just rewrite is relatively straightforward. Doing it that way has the advantage that new sub domains can be added purely using DNS though.
In terms of SSL if you are just using *.yyy.com as the subdomains you can use a wildcard certificate (I neither recommend nor disapprove of thwate, they just had a reasonable description of it). In the general case though hosting multiple SSL sites behind a single public IP address is a bit more tricky.
Is there consistency and/or a standard on how browsers send a url to a host related to trailing slashes?
Meaning, if I type in http://example.com in the address bar of a web browser, is the browser suppose to add a trailing slash (http://example.com/) or not?
The HTTP request sent from the browser to the server does not include the domain name, only the "path" portion (starting from the first slash after the domain name). Since the path cannot be empty, a / is sent in that case.
A sample GET request for the root of a web site might be:
GET / HTTP/1.0
The / above cannot be omitted.
As RFC 2616 tells:
3.2.2 http URL
The "http" scheme is used to locate
network resources via the HTTP
protocol. This section defines the
scheme-specific syntax and
semantics for http URLs.
http_URL = "http:" "//" host [ ":"
port ] [ abs_path [ "?" query ]]
If the port is empty or not given,
port 80 is assumed. The semantics
are that the identified resource is
located at the server listening for
TCP connections on that port of that
host, and the Request-URI for the
resource is abs_path (section 5.1.2).
The use of IP addresses in URLs
SHOULD be avoided whenever possible
(see RFC 1900 [24]). If the
abs_path is not present in the URL, it
MUST be given as "/" when used as a
Request-URI for a resource (section
5.1.2). If a proxy receives a host name which is not a fully qualified
domain name, it MAY add its domain
to the host name it received. If a
proxy receives a fully qualified
domain name, the proxy MUST NOT change
the host name.
Read more: http://www.faqs.org/rfcs/rfc2616.html#ixzz0kGbpjYWa
5.1.2 Request-URI
...
For example, a client wishing to retrieve the
resource above directly from the
origin server would create a TCP
connection to port 80 of the host
"www.w3.org" and send the lines:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org
followed by the remainder of the
Request. Note that the absolute path
cannot be empty; if none is present in
the original URI, it MUST be given
as "/" (the server root).
Read more: http://www.faqs.org/rfcs/rfc2616.html#ixzz0kGcaRbqU
Note that it's a very different matter when the URL has a path element:
http://example.com/dir
is a different URL than
http://example.com/dir/
and could in fact contain different content, and have a different search engine ranking.
As far as the protocol is concerned, http://example.com/something and http://example.com/something/ are quite different. Some servers might redirect you from one to the other if it is implemented in such a way.
As for the pure domain names, it always sends a request ending with a slash.
(The domain name itself is not included in the path section of an HTTP request, just as Greg Hewgill and the others wrote. It is, however, included in the headers.)
You can check it with a tool like Fiddler or WireShark.
I have 2 servers. One Reverse proxy on the web and one on a private link serving WebDAV.
Booth servers are apache httpd v2.
On the proxy I have:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /repo/ http : //share.local/repo/
ProxyPassReverse /repo/ http : //share.local/repo/
On the dav server I have:
<Location /repo/>
DAV on
Order allow,deny
allow from all
</Location>
The reverse proxy is accessed via https and the private server is accessed via http.
And there lies the problem!
Read only commands work fine. But when I want to move something I get 502 Bad gateway.
The reason for this is the reverse proxy not rewriting the url's inside the extended dav request.
The source URL is inside the header and is correctly transformed to http://share.local/file1.
The destination URL is inside some xml fragment I do not understand and stays https://example.com/file1 :(
Is there a standard way to let the apache correctly transform the request?
Thanks for your effort.
Hmm, found the answer. Always the same :)
I added the next line to my 'private server' config file:
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
RequestHeader edit Destination ^https http early
(e.g. of config location '/etc/httpd/conf.d/DefaultRequestHeader.conf')
and it worked. I don't know if this has drawbacks. I'll see.
The destination URL shouldn't be in XML but in the "Destination" header, as you already noticed. Maybe you were looking at the error response...
In general, this problem would go away when clients and servers implement WebDAV level 3 (as defined in RFC4918), which allows the Destination header to be just a relative path.