Archive

Posts Tagged ‘asp.net’

Preventing over posting or mass assignments vulnerability in ASP.Net MVC


In the previous post, I showed how the over posting or mass assignments vulnerability works in ASP.NET MVC. In this post, I will show how to prevent this vulnerability.

Never use your database object as a parameter for in an action method

Developers may get tempted to use the object they pass to the database. Here is an example

[HttpPost]
[ValidateAntiForgeryToken]
public async Task IActionResult  Create(User user)
{
    if (ModelState.IsValid)
    {
	_context.Add(userl);
	await _context.SaveChangesAsync();
	return RedirectToAction(nameof(Index));
    }
    return View(user);
} 

This is dangerous. With the above code, you will end up hurting the integrity of the data in your database. You should never, in my opinion, expose your database object to the outside world.

Recently, when scaffolding the Controller, the code generator adds a comment to warn developers about the overposting attack I don’t recall seeing it in ASP.NET MVC 4. It may have been added in ASP.NET MVC 5 or ASP.NET Core. The scaffolder also using the BindAttribute when generating the code which will discuss later on in this post.

Use different mode/view model for the Get and Post action methods

I like to use a model or view model which contains a subset of the properties that are in the database model. I use a different view model for the Get and Post request depending on the fields I want to show on the screen or capture from the user. I added new properties to the User model. I also created two view models. One for creating and updating a user (you can different VM for create and update if you want) and one for viewing a user.

public class CreateUserViewModel
    {
	public string Firstname { get; set; }
	public string Lastname { get; set; }
	public string Role { get; set; }
    }
public class UserViewModel
    {
	public int Id { get; set; }
	public string Firstname { get; set; }
	public string Lastname { get; set; }
	public string Role { get; set; }
	public DateTime LastUpdatedDate { get; set; }
    }

I created a branch in the code repository to demonstrate that https://github.com/lajak/SecureAspMvc/tree/OverPostingPreventionSeparateModel

With using the above code, we guarantee that the binder will only limited to the properties we have in the CreateUserViewModel for post request while for get request we have exposing more properties. Btw, creating a separate view model for get is not really necessary if your action method returns a view because your action method is returning the html which will be rendered by the browser. It becomes more crucial to have separate view model for read if your action returns data in json format.

In the controller, we need to map the values from CreateserViewModel to the DB user object.

  public async Task IActionResult Create(CreateUserViewModel user)
{
	var dbUser = new User();
	if (!await TryUpdateModelAsync(dbUser))
	    return NotFound();

	if (ModelState.IsValid)
	{
	    dbUser.LastUpdatedDate = DateTime.Now;
	    dbUser.CreatedDate = dbUser.LastUpdatedDate;
	    _context.Add(dbUser);
	    await _context.SaveChangesAsync();
	    return RedirectToAction(nameof(Index));
	}
	return View(dbUser);
}

Decorate properties with attributes

If you want to use one model, you can decorate the properties you don’t want the binder to bind with the [BindNever] attribute.

public class User
    {
	public int Id { get; set; }
	public string Firstname { get; set; }
	public string Lastname { get; set; }
	public string Role { get; set; }
	[BindNever]
	public DateTime CreatedDate { get; set; }
	[BindNever]
	public DateTime LastUpdatedDate { get; set; }
    }

Properties that are decorated with the BindNever attribute will not be assigned the value that is posted to the server. In other words, the binder will ignore it. There are few potential issues with using BindNever attribute.

  • High maintenance: developers need to remember adding BindNever property when adding new attribute if required and developers need to make sure that BindNever is not removed by mistake from one of the attribute
  • TryUpdateModelAsync: if you decide to have let’s say an admin page where you want administrator to be able to modify those attributes and you create a view model. The TryUpdateModelAsync will still ignore those properties that are decorated with BindNever and you need to assign those properties manually
  • I have read few reported issues that the Binder doesn’t respect BindNever or BindRequired when using the FromBody attribute

Use BindAttribute

One other option is to use the Bind attribute on the action method as such

public async Task IActionResult> Create([Bind("Firstname", "Lastname", "Role")] User user)

With this approach, you need to add the Bind attribute on every action method you want to prevent the over posting attack. You may have to revisit all your action methods every time you add or remove a property to the model.

Conclusion

As we have seen, there are few ways to protect our application from the overposting attack. I prefer to have view models. I feel it is the most flexible option as I can have a different view model per view or action method if required.

 

Advertisements
Categories: Security, Uncategorized Tags: ,

Over posting or mass assignments vulnerability in ASP.Net MVC


In Visual Studio, ASP.NET MVC comes with a great productivity feature called scaffolding. It is a code generation feature that generates a controller, view and the database calls if you are using Entity Framework to communicate to the database. If developers are not careful, they may expose the application to the over posting or mass assignment security vulnerability.

To understand the vulnerability, you need to understand how the Model Binder works in ASP.NET MVC.

The source code for this article is at https://github.com/lajak/SecureAspMvc/tree/OverPosting.

Let’s start with creating some artifacts

Create a new ASP.NET MVC project

Create a new model

        public int Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Role { get; set; }

Create UserController

  • Right click on the Controllers folder
  • Click on Add and select Controller
  • On the dialog, select MVC controller with read/write (lets keep it simple and not over complicate the example)
  • In the Create Action method, right click on the View function and click on Add View menu item

  • Fill the dialog as shown below.

On clicking the Add button, Visual Studio will generate a for creating a user. The view will be named create.cshtml and will be located in the Views\Users folder

Run the application and browse to http://localhost/user/create

  • Go back to the UserController
  • On Create Action method that is decorated with the HttpPost attribute, change the parameter type to UserModel and the parameter name to model as shown on the picture below. Also place a breakpoint at the return statement. We don’t have a view for the Index page. But we don’t need for this post.

Run the website in debug mode

Browse to http://localhost/user/create

Fill the form

Click the Create button

The code should break at the breakpoint

Hover over the model parameter and expand the properties

Notice that the Binder mapped the values that you entered in the form to the properties in the object

Now, stop the debugger and go to the Create.cshtml page. Let’s assume that the requirement was to hide the id field. The developer goes and delete the highlighted code

Run the code again and browse to the create method

Notice that the Id field is no longer showing up

If we run the code and populate the fields, the Id property won’t be populated.

As someone who wants to exploit this vulnerability, I can inject that id parameter into the request.

It is easier to use a tool like Fiddler or Burp to intercept the request and add the extra attributes to the payload but we can use the F12 developers tools as well

Click F12

Right click on

<form action="/user/Create" method="post">

Edit as Html and add the following line

<input name="Id" class="form-control" id="Id" type="number" value="111111111" data-val-required="The Id field is required." data-val="true">

Click outside the form attribute

Notice that we can see the field

Fill the other fields and hit create

Notice that the Binder binds the value of the id field to the Id property

Conclusion

We showed a trivial example for the over posting vulnerability. A more realistic example would be showing more or less fields based on the user role. If the developer only uses an if statement in the cshtml code to show fields based on the user role, the developer might be exposing the application to the over posting vulnerability. In the next post, I will show how to protect your application from this vulnerability.

Categories: Security, Uncategorized Tags: ,

Security tips: Record level authorization in your .NET application


Record level authorization is to verify that users are permitted to access the records they want to view, update or delete. I should say that not all applications I worked on or reviewed had that requirement. The requirement for some of the applications I had worked with was to implement role based authorization where users with certain roles can access certain areas of the application while other applications I had worked on required record level authorization.

Example of a record based authorization would be a bank account, only the account holders should be able to access the account and manage the account. Another example, in an insurance system, the policy holder should be the only one who can submit a claim and accept a settlement.

How to test if the application is vulnerable?

If you are a tester and doing white box testing, there isn’t a recipe that tells you that the application is 100% coded correctly. Let’s show a simple example using ASP.NET MVC on how you can test your application. Let’s say we have a URL such as http://hostname/users/Details/1. Given that the default route is {controller}/{action}/{id}, we can tell that the controller name is UsersController, the action method name is Details and the record Id is 1.

If the application is supposed to implement record level authorization, the system shouldn’t allow you to access record id 100 if you don’t have access to it. This can easily be tested by replace 1 with 100 in the url (e.g. http://hostname/users/Details/100)

How about POST requests? You can test POST request using the edit action method (i.e. http://hostname/users/Edit/1). The record id is usually passed in the payload. You can use the F12 developer tools to see the parameters passed to the server.

You can try to modify the id in the DOM if you don’t want to use other tools. It is easier to use a tool like Burp or Fiddler to intercept the request and modify parameters.

If you were able to modify a record that your user shouldn’t have access to, the application should fail the test case.

Conclusion

Record level authorization is a must for some systems but it is not necessary a requirement for other systems. You need to clarify the requirement with client to make sure your test cases are based on the requirements. The vulnerability is catastrophic for high profile applications if a hacker can exploit it. As a tester, your test cases should cover record level authorization related requirements.

Categories: Security Tags: , ,

Debug Aspnet Core HTTP Error 502.5 – Process Failure


Today after upgrading an aspnet core 1.0 to 1.1 I was getting HTTP Error 502.5 – Process Failure

In your project web.config:

  • Enable stdoutLogEnabled (set it to true)
  • Set full path for stdoutLogFile and make sure that the “logs” folder already exists
  • Then hit F5

<aspNetCore
processPath="%LAUNCHER_PATH%"
arguments="%LAUNCHER_ARGS%"
stdoutLogEnabled="true"
stdoutLogFile="C:\logs\stdout"
forwardWindowsAuthToken="false"/>

In my stdout file I got the following error:

The specified framework ‘Microsoft.NETCore.App’, version ‘1.1.0’ was not found.

– Check application dependencies and target a framework version installed at:

C:\Program Files\dotnet\shared\Microsoft.NETCore.App

– The following versions are installed:

1.0.0-rc2-3002702

1.0.1

1.0.3

– Alternatively, install the framework version ‘1.1.0’.

I was under the impression that I had already installed version 1.1.0. But it seems that I installed 1.0.3 instead J It was 1:00 AM LOL

Here is the trick part. When you go to https://www.microsoft.com/net/download/core to download .NET Core, the default selected tab is LTS instead of Current

Select Current and download the latest version of .NET Core SDK

 

Categories: asp.net Tags: ,

Performance tip – Caching expiry in web applications


Caching data that rarely change can give you a big performance boost especially if it takes time to fetch and/or calculate that data. In .NET 4.0, Microsoft introduced the .NET Memory Cache which is a thread safe cache that can be used Windows and Web applications. For more information about the MemoryCache class you can visit https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx

While I was doing a load test for web application for one of my clients, I noticed that the Queued Requests performance counter goes up every five minutes. By using a code profiler, it showed that there were many calls to refresh some of the cached data. Taking a closer look at the code below, if user 1 executing line (value = service.GetStreets();) while the other users are checking if value is cached, there is a potential of thousands of requests to fetch the same data especially if that data is frequently used.

We were using a CacheWrapper that applies a cache policy based on the cache name. With the CacheWrapper we can write the code to cache the Street Streets as follows:


public List<Street> GetStreets()
{

var value = CacheWrapper.Get(CacheNames.Streets) as List<Street>;

if (value == null)
{

    value = service.GetStreet();
    CacheWrapper.Set(CacheNames.Streets, value);

}

return value;

}

My first approach was to use a lock and double check the value


bool StreetsDataInitialized = false;
Object StreetsLock = new Object();

public List<Street> GetStreets()
{

var value = CacheWrapper.Get(CacheNames.Streets) as List<Street>;

if (value == null)
{
StreetsDataInitialized = false;

lock (StreetsLock)
 {
 if (StreetsDataInitialized)
 {
    return CacheWrapper.Get(CacheNames.Streets) as List<Street>;
 }

 value = service.GetStreets();
 CacheWrapper.Set(CacheNames.Streets, value);
 StreetsDataInitialized = true;

}

}

return value;

}

But there were many values that need to be cached and refreshed and I didn’t want to create two variables per cached value. I came up with a more generic way to achieve my goal. I started with the CacheLock Class

 public class CacheLock
  {
     public bool Initialized { get; set; }
     public object LockObject = new object();

 }

I used the ConcurrentDictionary to store the locks. I also created a generic GetOrSetCacheValue function which gets or creates a CacheLock for each cached data and invoke “function” if the data is not cached.


Public class CacheableLookupProvider
{
private static ConcurrentDictionary<string, CacheLock> LockDictionary = new ConcurrentDictionary<string, CacheLock>();
private readonly IStreetsService service;

Public CacheableStreetsProvider(IStreetsService service)
{
    this.service = service;
}

 private T GetOrSetCachedValue<T>(string cacheName, Func<T> function) where T : class
 {
    var value = CacheWrapper.Get(cacheName) as T;
    if (value == null)
     {
       var lockObject = LockDictionary.GetOrAdd(cacheName, new CacheLock());
       lockObject.Initialized = false;
      
      lock (lockObject.LockObject)
       {
         if (lockObject.Initialized)
         {
           return CacheWrapper.Get(cacheName) as T;
         }
         value = function();
         CacheWrapper.Set(cacheName, value);
         lockObject.Initialized = true;
       }
    }
    return value;
 }

 public List<Street> GetStreets ()
 {
    return GetOrSetCachedValue(CacheNames.Streets, () => service.GetStreets());
 }

 public List<Province> GetProvinces ()
 {
   return GetOrSetCachedValue(CacheNames.Provinces, () => service. GetProvinces());
 }

}

Categories: asp.net Tags: , , ,

Replace JavaScript serializer in Kendo controls with NewtonSoft


I have been doing code optimization for an ASP MVC 5 application that uses the Telerik Kendo controls. Some of the search results may return 7000 records in this project. After I had replaced the serializer, it took 30% less time to load the search results page.

 

The ASP MVC Helpers for Kendo controls by default use the System.Web.Script.Serialization.JavaScriptSerializer which is slow compared to the NewtonSoft Json serializer. Telerik made it easy to replace the default serializer.

Steps:

  • Created a class that implements IJavaScriptSerializer and implement the Serialize method.
    public class CustomKendoJsonSerializer : IJavaScriptSerializer
    {
       public string Serialize(object value)
       {
          return JsonConvert.SerializeObject(value); //use the serializer you want  here
       }
     }
    
  • Create a class that implements JavaScriptInitializer and implement the CreateSerializer method
    
    public class CustomKendoInitializer : JavaScriptInitializer
    
    {
    
    public override IJavaScriptSerializer CreateSerializer()
    
    {
    
    return new CustomKendoJsonSerializer ();
    
    }
    
    }
    
    
  • In the Application_Start event in the Global.asax file, register the new serializer
Kendo.Mvc.Infrastructure.DI.Current.Register<IJavaScriptInitializer>(() => new CustomKendoInitializer());
Categories: .NET, asp.net, C# Tags: , ,

ASP MVC 5: ViewBag does not exist in the current context


After upgrading one of my client’s applications from ASP MVC 4 to ASP MVC 5, We had designers errors related to Html Helpers and ViewBag in cshtml pages.

To fix those issues make sure you do the following:
Install Asp.NET Web Helpers Library from Nuget
Open the Web.config of the project and update the bindings if they haven’t been updated when installing the Nuget packages for example

<dependentAssembly>
<assemblyIdentity name=”System.Web.Mvc” publicKeyToken=”31bf3856ad364e35″ />
<bindingRedirect oldVersion=”0.0.0.0-5.2.2.0″ newVersion=”5.2.2.0” />
</dependentAssembly>

 

Find “webpages:Version” in the appsettings and update it to version 3.0.0.0. My web.config had

<add key=”webpages:Version” value=”2.0.0.0″ />

and I updated it to

<add key=”webpages:Version” value=”3.0.0.0″ />

Restart Visual Studio and rebuild. You may have to delete the bin folder for your project

 

About Lajak Technologies

A consulting firm in Ottawa, Ontario that provides services related to Microsoft technologies, Team Foundation Server, DevOps practices, security and more. Contact us today to help you solving your complex software problems. Visit us at http://www.lajak.com.

Categories: asp.net Tags: ,