Do not trust the data coming from the client.Almost all of this rule is well known and respected. We pass form validators through cookies, even URIs.
HTTP_HOST
and SERVER_NAME
.$_SERVER['HTTP_HOST']
. At a quick scan, I found quite a few cases where the data that came in this variable were left without filtering. Most often, only the existence of $_SERVER['HTTP_HOST']
, but they are not validated. GET / HTTP/1.1 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.3 Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cache-Control:max-age=0 Connection:keep-alive Host:site.dev Referer:http://site.dev/index.htm User-Agent:TelnetTest
HTTP_HOST
) Host:site.dev,
then the server will return 400 Bad Request
GET http://site.dev/ HTTP/1.1 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.3 Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cache-Control:max-age=0 Connection:keep-alive Host:site.dev Referer:http://site.dev/index.htm User-Agent:TelnetTest
GET / HTTP/1.1
GET http://site.dev/ HTTP/1.1
but GET http://site.dev/
Then all subsequent headers will be discarded, Nginx will work out the server section defined for server_name site.dev;
But HTTP_HOST
and SERVER_NAME
will not be determined.HTTP_HOST
an empty HTTP_HOST
fails: Host:
But it turns out to pass Host:_
or Host:""
$ telnet site.dev 80 Trying 127.0.0.1... Connected to site.dev. Escape character is '^]'.
GET http://site.dev/phpinfo.php HTTP/1.1 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.3 Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cache-Control:max-age=0 Connection:keep-alive Host:~%#$^&*()<>?@\!."'{}[]=+| Referer:http://site.dev/index.htm User-Agent:TelnetTest
_SERVER["SERVER_NAME"]: ~%#$^&*()<>?@\!."'{}[]=+| _SERVER["HTTP_HOST"]: ~%#$^&*()<>?@\!."'{}[]=+|
HTTP/1.1 200 OK Server: nginx/1.0.10 Date: Wed, 23 Jan 2013 10:31:14 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive
'/'
in the Host:
header, the server will return 400 Bad Request
.Host:../../
header will not work, such Host:http://evil.site
too $allowed_hosts = array('foo.example.com', 'bar.example.com'); if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $allowed_hosts)) { header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'); exit; }
HTTP_HOST
on the web server side.HTTP_HOST
add the following lines to Nginx's config: fastcgi_param HTTP_HOST1 $http_host; fastcgi_param HTTP_HOST2 $host; fastcgi_param HTTP_HOST3 $server_name;
server
sections defined: server { listen 80; server_name site1.dev; ... } server { listen 80; server_name site2.dev site3.dev; ... }
$ telnet site1.dev 80 Trying 127.0.0.1... Connected to site.dev. Escape character is '^]'.
GET http://site3.dev/phpinfo.php HTTP/1.1 Host:~%#$^&*()<>?@\!."'{}[]=+| User-Agent:TelnetTest
_SERVER["HTTP_HOST1"]: ~%#$^&*()<>?@\!."'{}[]=+| _SERVER["HTTP_HOST2"]: site3.dev _SERVER["HTTP_HOST3"]: site2.dev
fastcgi_param HTTP_HOST $host;
$ telnet site3.dev 80
GET /phpinfo.php HTTP/1.1 Host:~%#$^&*()<>?@\!."'{}[]=+| User-Agent:TelnetTest
server { listen 80 default_server; server_name ""; return 444; }
Source: https://habr.com/ru/post/166855/
All Articles