During several recent .NET (C#) security code review projects, multiple severe authorization bypass vulnerabilities were identified that allowed unprivileged remote users to access any page hosted on the web server, despite not having been provisioned with the appropriate required security access permissions. (Typically an attacker could leverage this type of vulnerability to access application administration functionality, both to obtain access to application data and to consolidate on-going future privileged access for themselves.)
The primary cause of these vulnerabilities was insecure use of the Server.Transfer method. As we continue to regularly identify and exploit this issue during our security reviews I thought I would write this quick blog in an effort to further raise awareness around this simple yet often overlooked security item.
Ultimately, any use of the Server.Transfer method that takes in user controllable input is likely to result in authorization bypass vulnerabilities (amongst other possible security issues). This is a known issue and is captured in the Microsoft Support KB Article ID: 320976 (http://support.microsoft.com/kb/320976/).
The underlying security “gotcha” that is not well communicated/publicized to developers is that when using the Server.Transfer method, the new page is being retrieved and presented by a separate handler, during which no authorization checks are performed regarding the actual remote user/callers identity. This is very different from the Response.Redirect method which instructs the user’s browser to request a different page, and forces a new page request - thus (hopefully) triggering an appropriate authorization check.
Unfortunately, much of the core standard documentation available to developers makes no mention of this important security factor, including those found on the MSDN site (http://msdn.microsoft.com/en-us/library/ms525800%28v=vs.90%29.aspx). In fact, on first glance the documentation on MSDN states that “Server.Transfer acts as an efficient replacement for the Response.Redirect method” but does not highlight the potential security implications of using this method.
(However, to be fair, the MS Patterns and Practices team do capture this exact issue in Chapter 6 of their “Improving .NET Application Performance and Scalability” publication: http://msdn.microsoft.com/en-us/library/ff647787.aspx)
As an example, the following vulnerable code snip is representative of those we regularly identify and leverage in proof-of-concept authorization bypass attacks:
protected void btnBack_Click(object sender, System.EventArgs e)
string returnUrl = Request["ReturnUrl"];
if (returnUrl == null)
returnUrl = "Login.aspx";
The function above will redirect the browser to the page contained in the ReturnUrl parameter, unless it is null in which case the browser will be redirected to the login page.
A typical application will have authorization checks to confirm if a user is authorized to view a requested page but as discussed previously when the Server.Transfer method is used, this logic will be bypassed (assuming that the page requested is hosted on the server). As the “ReturnUrl” parameter is user controllable, this function makes it possible to load any page on the server, including admin pages that lower privileged users should not be authorized to view. It is also possible to download DLLs from the /bin directory if the name of the dll is known (the dll can then be decompiled for further analysis). However, IIS does prevent the web.config file from being viewed.
If the Response.Redirect method was used in the code sample above, the browser would issue a new request for the page passed in the ReturnUrl parameter; because this would be a new request it would pass through the permissions checks again and the authorization bypass vulnerability would be prevented.
The Server.Transfer method of course can be used in valid circumstances such as to redirect to a page where the destination is not user-controllable (i.e. perhaps using an index of hardcoded ‘safe’, non-privileged destinations). Developers should take into account the differences between the Server.Transfer and Response.Redirect methods and understand that the Server.Transfer method is NOT always a secure replacement for the Response.Redirect method.