Popularity: 3 Simplicity: 3
Impact: 3
Risk Rating: 3
This is a vulnerability that slipped below the radar for most people, even though its impact is quite high if you look at it closely. The original publication of this issue demonstrated how an attacker can access portions of ASP code, but when examining it more deeply, this attack gives an attacker the ability to spoof hostnames in badly coded applications. Let’s take a closer look at how this works.
The trouble occurs while developing a web application in ASP or .NET, where a developer needs to access the IP address of the web server where the application resides.
A lot of developers will make one of the following calls in order to obtain the IP address or hostname of the web server the application is running on:
Request.ServerVariables("SERVER_NAME") (ASP) Request.ServerVariables["SERVER_NAME"] (.NET)
These calls return the "SERVER_NAME" value of the local environment variable. If the request originates from the Internet, the value of the variable is usually the web server’s IP address. If the request is from the actual web server, the variable’s value is
"localhost". This behavior is summarized in Table 3-1.
Developers often use this functionality to check whether or not the request is from localhost, and if the request is from localhost, then they will enable some level of restricted functionality to be opened. For example, developers will use this method to block requests to the administration page unless the request originates from localhost.
This specific vulnerability results from the way Microsoft used this method to handle their error files. By default, all IIS installations have the IISHelp directory that contains
Origin of request Value of SERVER_NAME variable
Web client www.site.com
Web server localhost
Table 3-1 The Value of the SERVER_NAME Variable Depends on the Origin of the Request
default IIS error messages. By default, the 500-100 error code is pointed at the “/iishelp/
common/500-100.asp” page. Thus, for any 500 error that occurs on the IIS server, IIS will use that page as a template for the response displayed back to the user. This behavior is very common for VBScript errors and database errors.
To determine if the error is being displayed to a local user, the code of 500-100.asp on Microsoft IIS 5.x uses the Request.ServerVariables("SERVER_NAME") API. If so, the error page dumps out source code that reveals the exact location where the error occurred. If the client is not local, then a generic error page is displayed, as shown in Figure 3-5.
The vulnerability is that the "SERVER_NAME" variable can be overwritten by specifying a value in either the Host: header or in the URL as GET http://spoof/
file.asp. For example, by identifying ourselves as localhost with this request:
GET http://localhost/product_detail.asp?id=a HTTP/1.0 Host: 192.168.1.1
Figure 3-5 A normal IIS error message when seen from the Internet client displays generic information.
we now receive the response shown next.
Notice that this time we receive source code that accompanies the error message.
While this, by itself, isn’t very impressive, what we like about this issue is the vulnerability’s sheer quirkiness and potential. It’s not a buffer overflow or a path traversal attack, but if you sit back a moment to consider the possible impact of this vulnerability, you’ll find it’s quite impressive. We can see multihost situations where developers could make use of this variable to restrict access to certain sites. In fact, we recently had the opportunity to make use of this issue and discovered that if we acted as localhost, we were taken to a developer administration page that allowed us to view all of the debugging information related to that web site. Thanks, developer!
This spoof attack also brings to mind another closely related development issue that you’ll commonly see. When using ASP and .NET, many developers will pull user input by using a call like this:
Username = Request["username"]
Let’s take a closer look at this. The correct way to determine if a user is coming from localhost or a specific IP address is to check the "REMOTE_ADDR" server variable.
This tells you the client IP address. That’s why developers might add a line like this in their code,
if(Request["REMOTE_ADDR"] == "127.0.0.1")
thereby sending users along their merry way to the administrative page. This works just as it should and will provide server variable’s proper value. But if you’re quick, you can easily identify that this can be bypassed by having users specify the value on the URL like this:
http://www.site.com/auth.aspx?REMOTE_ADDR=127.0.0.1
This spoof works because of the order in which input is processed by IIS. IIS first looks in the query collection for REMOTE_ADDR, then postdata, then cookies, and then finally server variables. Because the order in which the variables are checked begins with the query first, user-supplied data always takes precedence over server variables. The number of sites that are vulnerable to this type of mistake is quite amazing.