Rewrite HTTP/1.0 requests to HTTP/1.1 with Netscaler

Prevent IP disclosure to HTTP/1.0 requests from Exchange

I’ve already written about Remediating an Internal IP Disclosure with Netscaler, but I found out today that the route I’d chosen prevents Outlook from authenticating. Oops!

To summarize the earlier post, Exchange was leaking an internal IP and servername when an HTTP/1.0 packet was set without a host header to /autodiscover/autodiscover.xml. I initially tried to fix it by deleting the WWW-Authenticate and X-FEServer headers from the replies using Netscaler.

However, while that prevents the information from being leaked, it also prevents Outlook from properly loading when the traffic flows through Netscaler. In our case, internal traffic was fine, but people who rely on Outlook and autodiscover outside of our network couldn’t log in. I tested and removing the X-FEServer header permitted Outlook to load normally; it was removing the WWW-Authenticate header that caused the problem.

I tried out some alternate methods of blocking an internal IP in the WWW-Authenticate field (specifically, a reply containing basic realm="10.10.10.10), but it seems like there’s important authentication using that field. I came up with another approach which seems to be working: Since this vulnerability is the result of a HTTP/1.0 request, rewrite HTTP/1.0 requests to HTTP/1.1. HTTP/1.1 requires the host header field, which means that IIS won’t happily disclose internal IPs in response to a missing host header. HTTP/1.1 has been a standard since 1997 and there should literally be no device in the past 20 years which does not support it.

Let’s get to work. I’ll create a rewrite policy that looks for HTTP/1.0. If it’s found, replace it with HTTP/1.1.

add rewrite action RW_ACTION_HTTP1.0 replace HTTP.REQ.VERSION.MINOR "\"1\""
add rewrite policy RW_POLICY_HTTP1.0 "HTTP.REQ.VERSION.MINOR.EQ(0)" RW_ACTION_HTTP1.0
bind lb vserver VSRV-Exchange-OWA-External -policyName RW_POLICY_HTTP1.0 -priority 110 -gotoPriorityExpression END -type REQUEST

Let’s test and make sure that the internal information is no longer returned:

GET /autodiscover/autodiscover.xml HTTP/1.0

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 21 Sep 2021 14:16:46 GMT
Connection: close
Content-Length: 334
Strict-Transport-Security: max-age=15552000

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Hostname</h2>
<hr><p>HTTP Error 400. The request hostname is invalid.</p>
</BODY></HTML>
closed

Great! The request is rejected (404) because HTTP/1.1 requires a host header, and this rewritten HTTP/1.0 request doesn’t have one.

Built with Hugo
Theme Stack designed by Jimmy