Entries in .NET (2)


Enumerating .NET MVC Application Endpoints with Roslyn

When performing security code reviews of .NET web applications, one of the first goals for the reviewer should be to enumerate the external facing attack surface. For ASPX based applications this is achieved by enumerating all files with an aspx or ascx extension. Additionally, the ‘web.config’ file should be parsed for any exposed HttpModules, HttpHandlers and configured web services. Over the years, more and more applications have been transitioning to .NET MVC. With this transition the process for enumerating endpoints becomes a bit trickier.

When encountering a .NET MVC web application, Controllers handle the processing of incoming requests and are tied to exposed URL endpoints in the application. To successfully enumerate an application’s web attack surface, finding all classes that inherit from Controller base classes and enumerating their public methods is required. Additionally, .NET MVC introduces Filter Attributes that can be set at a Global, Controller (class) or Action (method) level.

For example, the DataController class in the code snippet below exposes an action named Index() that returns the current time. This action is decorated with the OutputCache action filter.

Therefore, prior to executing the code within the method, the logic of the ‘OutputCache’ action attribute will be executed first. There are out of the box Filter Attributes provided by .NET, or you can create your own. The ‘HttpGet’ attribute set on the method scopes the request to accepting only ‘GET’ requests. The ‘Route’ method defines the URL endpoint a user would need to hit in order to be routed to run the ‘Index()’ method.

Snippet 1 – Controllers\DataController.cs

public class DataController : Controller
	public string Index(){
		return DateTime.Now.ToString("T");

It is very common for applications to use Filter Attributes to handle security related tasks. Some frequently observed examples of security related logic are:

  • Authentication enforcement

  • User/role based access control

  • CSRF token validation

  • Cache control headers

  • Setting of HTTP security headers

Having the ability to enumerate all exposed application endpoints and their associated Filter Attributes becomes very powerful during a manual security code review. The code reviewer will have the ability to quickly identify the application’s attack surface and identify gaps in security coverage based on the Filter Attributes assigned.


In order to perform our enumeration we used the .NET Compiler Platform (Roslyn) which provides open-source C# and Visual Basic compilers with powerful code analysis APIs. It enables building code analysis tools with the same APIs used by Visual Studio. It is a workable ‘compiler as a service’ API – that is to say that it exposes the C# compiler as an API for developers to call and work with the syntax tree. The APIs allow us to automate the enumeration process very accurately compared to simply using regex based ‘grepping’.

The Roslyn APIs are available by default within Visual Studio 2015. Alternatively, it can be installed through NuGet by installing the ‘Microsoft.CodeAnalysis’ package.

Using the APIs, we can iterate through all ‘*.cs’ files within a given directory and parse each file using the ‘CSharpSyntaxTree.ParseText’ method. This method turns the parsed file into a syntax tree that can then be analyzed.

using (var stream = File.OpenRead(path))
    var tree = CSharpSyntaxTree.ParseText(
        SourceText.From(stream), path: path);

    SyntaxNode root = tree.GetRoot();

In order to identify the classes that inherit from a Controller class, you can traverse the syntax tree and check the base type of the class.

public bool inheritsFromController(SyntaxNode root, String args) {
    bool isValid = false;
    try {
        isValid = root.DescendantNodes()
            .Equals("ApiController") || 

Retrieving the class declaration for the Controller and all of its public methods can be performed using the following code.

ClassDeclarationSyntax controller =
.First(); //Get all the public methods in this class IEnumerable<MethodDeclarationSyntax> methods = from m in root.DescendantNodes() .OfType<MethodDeclarationSyntax>() where m.Modifiers.ToString().Contains("public") select m;

Now that the Controller and its public methods are enumerated we can extract the attribute assigned at both the class and method levels. The attributes can be retrieved by reading the ‘AttributeLists’ value of the ClassDeclarationSyntax and/or MethodDeclarationSyntax objects.

Public methods with a route defined are potential entry points to the application and can be invoked through HTTP requests. Before invoking the code within the method, the request will be processed by the filter attributes defined globally, at the controller level and at the method level.

.NET MVC Enumeration Tool

We are releasing a tool that utilizes the Roslyn API to automate the enumeration of .NET MVC controller entry points. The tool runs against a given directory and identifies:

  • All classes that inherit from a Controller class

  • All public methods within Controller class

  • Attributes assigned to a method including the ones set at the class level

The basic usage of the script is as follows:

> DotNetMVCEnumerator.exe -h

Usage: DotNetMVCEnumerator.exe

[-d Directory To Scan  *Required]

[-a Attribute Name to Search]

[-n Attribute Name To Perform Negative Search]

[-o File Name to Output Results as CSV]

[-h Display Usage Help Text]

Sample Usage 1 - Scan code within a directory and write output to the ‘results.csv’ file.

> DotNetMVCEnumerator.exe -d “C:\Code” -o results.csv

Sample Usage 2 - Scan code and only include results of methods containing the ‘CSRFTokenValidate’ attribute filter. The output is written to the console and to the ‘results.csv’ file.

> DotNetMVCEnumerator.exe -d “C:\Code” -o results.csv -a CSRFTokenValidate

Sample Usage 3 - Scan code and only include results of methods missing the ‘Authorize’ filter attribute. The output is written to the console and to the ‘results.csv’ file.

> DotNetMVCEnumerator.exe -d “C:\Code” -o results.csv -n Authorize

The tool is very useful to quickly identify any methods that may be missing authorization controls enforced through filter attributes. The CSV output is very helpful during manual code reviews in order to:

  • Quickly identify test/debug or administrative functionality that is accidentally exposed based on the name of the Controller or method name or URL route path.

  • Identify classes that are missing filter attributes and therefore may be missing the enforcement of security controls.

  • Keep track of your manual code review progress by leaving comments in the spreadsheets as each external entry point is reviewed.

Excel can be used to perform column based filtering based on your needs. 

The source code and binary for the tool can be found on our Github repository:


.NET Server.Transfer vs Response.Redirect - Reiterating a Security Warning

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 ( 

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 (  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:

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.