ORM\ERM and hidden fields

Hidden fields can pose a major security risk when used in conjunction with ORM\ERM. An ORM\ERM provides a way to map your classes into a database scheme and usually provides code to retrieve and save the objects. Sometimes the mapping is a simple 1:1 between the class and the database tables behind it or it can be more complex with a class represented across multiple tables. Either way a class or classes are generated that represent the information you are attempting to model, these classes can then push and pull information from a database table.

Often the classes representing the data in the database are generated and overwritten on every database\model change depending on how the system works.

It is often tempting to use these generated classes as your model for a screen as they often closely represent the data that is being updated.

With the ability to add a partial class (or buddy class) to hold the model attributes this becomes even more tempting

https://msdn.microsoft.com/en-us/library/system.web.mvc.modelmetadata(v=vs.118).aspx

An example of the bubby class system is shown below, first there is a generated class (with a partial modifier)

////below is the generated class which will be overwritten

public partial class MyClass

{

public int MyClassId { get; set; }

public string Name { get; set; }

etc

}

 

Next a buddy class is set up (usually in a different file) with the fixed display and validation information

[MetadataType(typeof (MyClassAnnotations))]

public partial class MyClass

{

}

public class MyClassAnnotations

{

/// <summary>Gets or sets the Name </summary>

[Display(Name = “Name”)]

[DataType(DataType.MultilineText)]

[Required(ErrorMessage = “Name.”)]

public string LookupName { get; set; }

etc

Now we can regenerate our ORM entity classes without overwriting our display\validation attributes – great.

This approach has the advantage of promoting reuse of the generated and buddy classes rather than the hassle and overhead of creating a view model for every screen. Also if a view model is created for every screen the view models will need mapped into the generated entity in order to save the data to the database using the ORM\ERM system. A good solution then? Well at first this seems to be the obvious solution however it will soon run into security issues.

Lets take a AccountUser entity. This is being used represent a user within a system along side the information in the authentication db. The class could look something like below  (note this is an extreme example to illustrate the point):

public class AccountUser

{

public string UserName {get; set};

public string Email {get; set};

public Guid RoleId {get; set};

public string Name {get; set};

public string Address {get; set};

/// another 10 user details type fields

}

So for some reason (in this example) the Email and RoleId are being held alongside the Authentication database and so have been denormalised and are now stored in two places.

Say we need a screen to update the user’s general details – name, address, telephone number etc. The AccountUser class would seem like a good starting point for a model. Therefore we create a view using the AccountUser as our model and add the fields we want to update – name, address, telephone number etc.

Unfortunately on saving the controller throws an error Email, Username, RoleId are missing. The solution add them as hidden fields as below to the view

@Html.HiddenFor(model => model.Email )

@Html.HiddenFor(model => model.RoleId )

@Html.HiddenFor(model => model.UserName )

Great our form now works and saves – all is well.

Say a hacker logs in, all they have to do is register as basic user go to edit user and hit F12 find the hidden field that holds the RoleId, edit it and click save. It is likely this will go straight into the database via the ORM\ERM. If your RoleId is of type int the value of other roles may be obvious (1,2,3,4). If it is a Guid it may be more difficult but may still be possible to identify different RoleIds from looking at other screens, dropdowns and menus.

There is a range of different attacks that could be launched using this approach – such as updating the email address. Although an extreme example this sort of attack has occurred for real.

Also the hidden fields are leaking information. If we have left the data off the screen because we don’t the user to see it, be aware the value is sitting in plain text on the screen. The hacker or user just needs to hit F12 and explore the dom to see it.

Alternatively if you are leaving a field off the screen because the user does not have the right to edit it (but you are happy for them to see it) then you probably don’t want it in a hidden field unless you overwrite it in the controller as again the value can easily be changed. If the user does have the right to edit it but on a different screen you are maybe skipping any custom complex validation connected to the other screen.

All of this really suggests that instead you should be using a view model, for example

public class AccountUserViewModel

{

public string Name {get; set};

public string Address {get; set};

/// another 10 user details type fields

}

We will know the username to save this record against as it should be the logged on user’s username therefore that can be left off the model.

Unfortunately AccountUserViewModel now needs mapped in to an existing AccountUser entity class for saving.

To update a record we may have to retrieve the AccountUser object we are trying to update, update the fields in the AccountUser object using AccountUserViewModel  model and finally then save the updated AccountUser object back to the database. Also we should think about checking row version for concurrency.

The alternative is try and encrypt the hidden field values but that is probably adding complexity and will be closely scrutinized during any security review, leading to a lot of questions you may or may not be able to answer.

Hidden fields should probably be regarded with suspicion-

  • Why are they there?
  • What happens if they are tampered with?
  • Is the information left off the screen because it is secret?

It may be best to not to use them and if you do add a comment to explain why it is safe.

What about other technologies and settings that may help this situation:

Does using HTTPS\SSL help with this problem?

No HTTPS\SSL will

  • Verify that the content displayed on the page came from where it should have
  • The transmission has not be tampered with
  • Finally the transmission cannot be read by a third party

Basically the altered data cannot be intercepted easily by a third party but the data from the web page is still passed.

What about anti forgery tokens (CRSF)?

No anti forgery tokens check that the information being sent to the server came from a web page issued by the web server in the first place.

Neither of the above technologies are of any help. As a rule of thumb you should always try to create ViewModels and map them. The mapping can be performed using automapper which I will discuss the pros and cons of in another post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s