Skip to main content

Internet Information Services(IIS) reveals its real or internal IP Address



In the ever changing world of global data communications, inexpensive Internet connections, and fast-paced software development, security is becoming more and more of an issue. Security is now a basic requirement because global computing is inherently insecure.

Keeping that in mind, we recently ran our flagship product through a security audit. It was such a helpful exercise in tying-off any remaining lose ends in our application in terms of application security. 

Based on the security audit report, there was a relatively minor issue that appeared when accessing the /images directory of our application. Turns out that the Location response header of the 301 request returns an Internal IP address. The issue is detailed below.



Issue reported

Internet Information Services (IIS) may reveal its real or internal IP address in the Location header via a request to the /images directory. The value returned whilst pen testing is https://10.0.0.10/images.



The risk

Information regarding internal IP address ranges is usually hidden from internet facing systems and can provide an attacker with useful information about internal network structure which can be later used in a targeted attack. 



The recommendation

As a matter of best practice, internal information should be removed or masked.



Understanding the Issue

When the /images directory is requested, IIS ensures that /images directory has “Directory Browsing” enabled. If it is not enabled and the directory does not have a Default.html/htm page within the directory, a “Forbidden” page needs to be shown.

When the request method used is HTTP/1.0, the Location response header of the 301 request returns an Internal IP address. This needs to be mitigated! 

In terms of HTTP Headers, the following 2 request, responses are made:
  • Response Code 301 /images => /images/
  • Response Code 403 Forbidden
The actual interactions between the browser and server are listed below.

* Response Code 301 /images => /images/

The request
Remote Address
10.0.0.10: 443
Request URL
https://dev-2008-iis01.pv.local/images
Request Method
GET
Status Code
301 Moved Permanently

Request headers
Accept
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding
gzip,deflate,sdch
Accept-Language
en-US,en;q=0.8
Connection
keep-alive
Cookie
ASP.NET_SessionId=e5hlhemgbpcu0a3k0dphke5y; __RequestVerificationToken=ufS2rtMQMEHuRRQdV8umKRyJF4LMN4Pt9tNbF2QEDxQhvLWlZiycwD_vYNVlUwi6858t5-m8oLvW1CppLT1VuXVPeLE1
Host
development-server-iis.local
User-Agent
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36

Response headers
Content-Length
162
Content-Type
text/html; charset=UTF-8
Date
Tue, 22 Jul 2014 03:27:31 GMT
Location
https://development-server-iis.local/images
Server
Microsoft-IIS/7.5
X-Powered-By
ASP.NET


* Response Code 403 Forbidden

The request
Remote Address
10.0.0.10:443
Request URL
https://development-server-iis.local/images/
Request Method
GET
Status Code
403 Forbidden

Request headers
Accept
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding
gzip,deflate,sdch
Accept-Language
en-US,en;q=0.8
Connection
keep-alive
Cookie
ASP.NET_SessionId=e5hlhemgbpcu0a3k0dphke5y; __RequestVerificationToken=ufS2rtMQMEHuRRQdV8umKRyJF4LMN4Pt9tNbF2QEDxQhvLWlZiycwD_vYNVlUwi6858t5-m8oLvW1CppLT1VuXVPeLE1
Host
development-server-iis.local
User-Agent
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36

Response headers
Content-Length
1233
Content-Type
text/html
Date
Tue, 22 Jul 2014 04:0:16 GMT
Server
Microsoft-IIS/7.5
X-Powered-By
ASP.NET


Verification of the exploit

As you saw in the initial response header from the server, the Location header (highlighted in red) does not actually reveal an IP address (which is what we want).

This is deceiving as it turns out, IIS may reveal the internal IP Address if the request method is HTTP/1.0 instead of HTTP/1.1

To verify this issue, I used https://development-server-iis.local/images/. As this issue is reproducible in HTTP/1.0, we can verify it via TELNET.Using TELNET, make the request as follows:

telnet /images HTTP/1.0

The following Response is received:


The resolution

As IIS server sometimes leaks its internal IP address in a header field, to combat it we can specify the host name to use for redirection. To do so, we will use “ServerRuntime”.

The <serverRuntime> element configures the following settings that are related to the Internet Information Services (IIS) 7 server runtime:
  • Setting the enabled attribute to true will configure IIS 7 to serve content on the URL where the <serverRuntime> element is configured; setting the enabled attribute to false will configure IIS 7 to not serve content for that URL.
  • The alternateHostName attribute specifies a host name that is different from the computer name in the HTTP Content-location head
Note: This is compatible in the following versions:
VersionNotes
IIS 8.5The <serverRuntime> element was not modified in IIS 8.5.
IIS 8.0The <serverRuntime> element was not modified in IIS 8.0.
IIS 7.5The authenticatedUserOverride attribute was added in IIS 7.5.
IIS 7.0The <serverRuntime> element was introduced in IIS 7.0.
IIS 6.0The <serverRuntime> element replaces the following IIS 6.0 metabase properties:
  • SetHostName
  • MaxRequestEntityAllowed
  • UploadReadAheadSize

    Information you need

    Before you commence, you will need to know the 

    Name of website
    This is visible in “Internet Information Services Manager” (inetmgr)
    As you can see, in our case, the name of the Website is “WebTier”



    Host Name
    In our case, the name of the host was “development-server-iis.local

    Steps to resolve

    1. Log into the server that hosts the Web Tier of Support Point application as an Administrator and open an administrator command prompt.
    2. Navigate to AppCmd.exe (is located in the %systemroot%\system32\inetsrv\)
    3. Using AppCmd enable server runtime for your Application using the following command
      appcmd.exe set config "WebTier" -section:system.webServer/serverRuntime /enabled:"True" /commit:apphost (Note: Here you will need to replace WebTier with the name of your website.)
    4. Using AppCmd enable server runtime for your Application using the following command
      appcmd.exe set config "WebTier" -section:system.webServer/serverRuntime /alternateHostName:"development-server-iis.local" /commit:apphost (Note: Here you will need to replace WebTier with the name of your website. You will also need to replace development-server-iis.local with your host name.)
    5. Restart the website via “Internet Information Services Manager” (inetmgr)


    Verification of Resolution

    To verify if this has resolved the issue, we can use telnet in a similar way to when we verified the existence of the exploit. The response received shows that the issue has been resolved.

    Using TELNET, make the request as follows:

    telnet /images HTTP/1.0

    The following Response is received:






    References: http://www.iis.net/configreference/system.webserver/serverruntime

    Comments

    1. The command "telnet /images HTTP/1.0" doesn't return what you have documented here.
      I'm working on a Server 2012 R2 server running Exchange 2016.

      When I run "telnet /images HTTP/1.0" I get

      C:\Windows\System32\inetsrv>telnet /images HTTP/1.0

      telnet [-a][-e escape char][-f log file][-l user][-t term][host [port]]
      -a Attempt automatic logon. Same as -l option except uses
      the currently logged on user's name.
      -e Escape character to enter telnet client prompt.
      -f File name for client side logging
      -l Specifies the user name to log in with on the remote system.
      Requires that the remote system support the TELNET ENVIRON option.
      -t Specifies terminal type.
      Supported term types are vt100, vt52, ansi and vtnt only.
      host Specifies the hostname or IP address of the remote computer
      to connect to.
      port Specifies a port number or service name.

      Please help.

      ReplyDelete
      Replies
      1. Here is how-to:
        telnet [Your IIS IP address] 80
        and then type the below when you get a new prompt:
        GET /images HTTP/1.0

        Sample below:
        > telnet 192.168.85.22 80


        Connecting to 192.168.85.22:80...
        Connection established.
        To escape to local shell, press 'Ctrl+Alt+]'.
        GET /images HTTP/1.0

        HTTP/1.1 404 Not Found
        Content-Type: text/html
        Server: Microsoft-IIS/7.5
        X-Powered-By: ASP.NET
        Date: Wed, 04 May 2016 06:16:31 GMT
        Connection: close
        Content-Length: 1238

        Delete

    Post a Comment

    Popular posts from this blog

    IIS Request Filtering to block HTTP Verbs (For example Trace)

    The issueRequest Filtering is a built-in security feature that was introduced in Internet Information Services (IIS) 7.0. This can be used to block specific verbs like "Trace".

    When request filtering blocks an HTTP request, IIS 7 will return an HTTP 404 error to the client and log the HTTP status with a unique substatus that identifies the reason that the request was denied. Verb Denied.

    HTTP SubstatusDescription404.5URL Sequence Denied404.6Verb Denied404.7File Extension Denied404.8Hidden Namespace404.1Request Header Too Long404.11URL Double Escaped404.12URL Has High Bit Chars404.13Content Length Too Large

    Unit Testing HttpContext.Current.Session in MVC3 .NET

    We recently changed some functionality where during the "CREATE" process, we go through a wizard to save application data. This data is saved only to the session in the final step when the user clicks the final submit.

    This was easy enough to implement but when I started writing unit tests for my static methods that Add, Update, Delete or Modify the contents of our application data in the session, I got the following error:
    System.NullReferenceException: Object reference not set to an instance of an object.

    Turns out I had forgotten to setup the HttpContext.
    The following "TestInitialise" method fixed my problem :)

    [TestInitialize]
    public void TestSetup()
    {
    // We need to setup the Current HTTP Context as follows:

    // Step 1: Setup the HTTP Request
    var httpRequest = new HttpRequest("", "http://localhost/", "");

    // Step 2: Setup the HTTP Response
    var httpResponce = new HttpResponse(new StringWriter());

    // Step 3: Se…