I'm currently on the process of trying fix a site vulnerability, basically it is one type of the "Improper Input Handling" attack.
Let's say my website is www.mywebsite.com
and there is hacker's website www.hacker.com
whenever there is a request send to www.mywebsite.com with modified "Host" header point to www.hacker.com, my site will create a redirect to www.mywebsite.com along with whatever the url it was.
e.g.
Normal:
Host: www.mywebsite.com
GET www.mywebsite.com/get/some/resources/
Reponse 200 ok
Hack:
Host: www.hacker.com (#been manually modified)
GET www.mywebsite.com/get/some/resources/
Response 302
Send another Redirect to www.hacker.com/get/some/resources
My website is running on Tomcat 7, I tried some solution with set up the virtual host by point the unknown host to a defaultlocalhost which suppose to do nothing. but it still send the redirect for some reason.
Here attached is my server.xml host configure:
<Engine name="Catalina" defaultHost="defaultlocalhost" jvmRoute="jvm1">
<Host name="www.mywebsite.com" appBase="webapps"
unpackWARs="true" autoDeploy="false" deployOnStartup="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="defaultlocalhost" >
</Host>
So, my question is, Am I on the right track to prevent this kind of attack ? If yes, what I did wrong that still not working? (The ultimate goal is, if it is not the legit Host that been passed in, the request should be discard/ignored/return 404 but not redirect with 302)
Thank you in advance.
More references about the attack here :
http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html
http://projects.webappsec.org/w/page/13246933/Improper%20Input%20Handling
Oh well, end up answer my own question.
After join the Tomcat user mailing list (subscribe email address: users#tomcat.apache.org).
There is the guy named Andre helped me get this resolved:
basically what I did wrong is missing appBase in my defaultlocalhost
<Host name="defaultlocalhost" appbase="whatever" >
</Host>
The above configure successfully returned 404 status whenever a illegal request was been send. the reason is that whenever you don't set the appbase it always default to webapps so it essentially didn't do anything with my original configure.
Hope this can help anyone who had similar issue.
Update 7/10/2020
A 403 can be returned by adding in a RemoteAddrValve and blocking all ip's. The example is based on Tomcat 9.
http://tomcat.apache.org/tomcat-9.0-doc/config/host.html#Request_Filters
<Host name="defaultlocalhost" appbase="whatever">
<!-- deny all remote addresses to this host -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="\d+\.\d+\.\d+\.\d+"/>
</Host>
Although it didn't exist at the time this question was asked, Tomcat 7.0.87 introduced a new property allowHostHeaderMismatch on the connector (cf. documentation). If you set it to false (default since Tomcat 9.0), Tomcat will return a 400 Bad Request error whenever the Host header does not match the request line:
<Connector port="8080" allowHostHeaderMismatch="false" />
Related
Using an Azure Server Core 2019 VM I've set up a number of docker containers with ISS/ARR 3.0 as the reverse proxy.
When I access the host url: "http://[hostname]/deploy" i expect the RP to redirect to http://[docker ip]:81
81 is the exposed port of the separate internal docker container that "deploy" runs on. FYI: This is mapped to host port 1322... accessing hostname:1322 via an external browser works fine.
(I've also tried using a rewrite rule to [hostname]:1322 and [docker ip]:1322)
No matter what i do, I always get 404 (not found)
I can't figure out why. Is there something in Azure itself messing this up? The only networking I appear to have available to docker in windows is NAT (via docker network ls). I've got the correct IP address of the target docker container via "docker inspect [container]" but I think this is the IP address as exposed to the host, not that can be seen by other containers running on the host.
How do I know what the internal docker IP is that is available to other running docker containers for the ARR rule (or is there another way to set this up so it knows the rule dynamically?)
my ARR web.config is:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="deploy" stopProcessing="true">
<match url="^(.*)/deploy" />
<action type="Rewrite" url="http://172.23.60.148:81" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
My reverse proxy docker file is:
FROM mcr.microsoft.com/windows/servercore/iis
# Download and install the required URL rewrite and Application Request Routing modules. Clean up after!
ADD http://go.microsoft.com/fwlink/?LinkID=615137 /install/rewrite_amd64.msi
ADD http://go.microsoft.com/fwlink/?LinkID=615136 /install/ARRv3_setup_amd64_en-us.msi
RUN msiexec.exe /i C:\install\rewrite_amd64.msi /qn /log C:\ms_install.log & \
msiexec.exe /i C:\install\ARRv3_setup_amd64_en-us.msi /qn /log C:\arr_install.log & \
rd /s /q c:\install
# Enable proxy feature for IIS. Allows us to act as a reverse proxy
RUN .\Windows\System32\inetsrv\appcmd.exe set CONFIG -section:system.webServer/proxy /enabled:"True" /commit:apphost
# The web config should contain our routing to other containers
ADD ./web.config /inetpub/wwwroot/web.config
So, it turns out that the problem is not docker at all but ARR.
When you add the rewrite rule, it's logical to expect this "^(.*)/deploy" to be the match criteria, i.e. "ending with /deploy". The rewrite rule tester in IIS even works correctly when you try it out.
Turns out, IIS doesn't pass the / to the rewrite rules engine. It only passes the text "deploy"... so the rule never matches and it then passes it onto the underlying IIS site instead of the the target... and of course /deploy doesn't exist in the underlying site, hence the 404.
Related ARR issues here
URL rewrite in IIS 8.5 is not working I'm getting 404 instead
Url Rewrite in IIS get 404
I have a little problem with CUPS 2.2.7
This is my /etc/hosts file:
127.0.0.1 example.com
127.0.0.1 localhost
in http://localhost:631/ CUPS is working right
but in http://example.com:631/ it doesn't work on the same pc.
The message error in View error log is that one:
E [21/Feb/2019:11:54:18 +0100] [Client 33] Request from "localhost" using invalid Host: field "example.com:631".
The web page on Firefox print an error message Invalid request and give me an Error (error code: 400) but seems point on CUPS.
How to solve this problem so that example.com:631 points to localhost and CUPS answers it successfully instead of Error 400: Access Denied.
By default cups servers HTTP requests only with HTTP Host header equal to "localhost". To allow it servicing requests for additional HTTP host headers use ServerAlias directive as described in the man cupsd.conf documentation. It's common to do the most unsafe thing and add
ServerAlias *
to /etc/cupsd.conf to allow all possible HTTP host headers to be serviced.
I know this is old, but I too was experiencing the same issue recently and I resolved it by updating the following line in cupsd.conf from:
Listen 0.0.0.0:631
changed to:
Listen *:631
For those that maybe care to know, I'm running CUPS within a docker container, and this change corrects the "Bad Request" response.
I created a new Azure VM, installed the LAMP stack, and when I visit the domain name in a browser, it serves the following error, which I am unable to find any information on through Google or Stack Overflow:
<?xml version="1.0" encoding="utf-8"?><Error><Code>InvalidQueryParameterValue</Code><Message>Value for one of the query parameters specified in the request URI is invalid.
RequestId:45ba52f4-0001-0086-13ed-e545cf000000
Time:2015-09-03T02:07:58.4816344Z</Message><QueryParameterName>comp</QueryParameterName><QueryParameterValue /><Reason /></Error>
When I use wget http://localhost while logged in through SSH, I get this error instead:
--2015-09-03 02:05:57-- http://localhost/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 65 [text/html]
index.html: Permission denied
Cannot write to ‘index.html’ (Permission denied).
The apache config for the default site is plain:
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster#localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
How do I get this VM to start serving using Apache?
This can occur on the 'Static Website hosting' feature if you point your CNAME to the wrong Azure server.
You must use the server DNS name that contains web in the name and not blob.
The first error (when opening from Internet) is (most probably) showing that you do not try to access the VM URL, but another service instead (i.e. Azure storage service, or some other Azure service)
To make things more confusing for newcommers Microsoft has now 2 parallel types of services - one is called classic and the other is called resource manager. In order to give you best answer, I have to know how did you create your VM - using the classic or using the resource manager (or shortly ARM) mode. If it was the clasic, your VM should live in a domain something like: mylinuxvm.cloudapp.net. You can check this going to the management portal then selecting VM and checking its settings / properties. Is it is the case, the only thing you need to add is an Endpoint for port 80, so that Internet traffic coming on TCP port 80 will be redirected to your VM.
If it is an ARM VM, you need a network security group rule that will send traffic on port 80 to your public IP Address, which has to be associated with the VM.
The second error:
When I use wget http://localhost while logged in through SSH, I get
this error instead:
--2015-09-03 02:05:57-- http://localhost/ Resolving localhost (localhost)... 127.0.0.1 Connecting to localhost
(localhost)|127.0.0.1|:80... connected. HTTP request sent, awaiting
response... 200 OK Length: 65 [text/html] index.html: Permission
denied
Cannot write to ‘index.html’ (Permission denied).
You get because you are using wget instead of curl. The difference is that curl will just render the result in stdout while wget tries to downalod and save the contet. The error is quite clear:
Cannot write to ‘index.html’ (Permission denied).
Which means you are executing the command in a folder to which you do not have write permission. This is usally the home of the root user when you do not do sudo before executing the command.
I was having the exact same problem as this guy.I followed the answer but that gives me
INVALID Profile
I have only tried to configure external.xml file to my External IP.But everytime i reloadxml it tells me my sip profile conf is invalid
What i tried:
Made sure that the ports are not blocked
Can reach the port from telnet command telnet MY_IP MY_PORT
Please throw some light anyone.Thanks
Solved it.
I was changing the wrong xml tag.Needed to change
<param name="ext-rtp-ip" value="MY_EX_IP"/>
<param name="ext-sip-ip" value="MY_EX_IP"/>
I'm trying to setup IIS 7.5 as reverse proxy to connect to Tomcat 7 via ARR 3.
For some reason when IIS forwards the request, the x-forwarded-for header contains the remote port, so instead of showing something like: 123.124.125.126 I see 123.124.125.126:54321
Unfortunately that does not work with RemoteIpValve, which expects the IP address only.
Is there a way to remove the port from IIS? or in RemoteIpValve?
Update: I tried running the command below and I can see that it updated applicationHost.config but I still see the port number (restarted IIS):
appcmd.exe set config -section:system.webServer/proxy /includePortInXForwardedFor:"false" /commit:apphost
Thanks!
I ended up using the following workaround:
On IIS, in %System32%/inetsrv/config/applicationHost.config I added the following snippet at system.webServer/rewrite/globalRules/rule [name=ARR*]:
<severVariables>
<set name="HTTP_X_REMOTE_ADDR" value="{REMOTE_ADDR}" />
</severVariables>
Then I specified that name to the RemoteIpValve in Tomcat's server.xml
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-remote-addr" />
To use the newly added header instead of X-Forwarded-For