Preventing Insecure Object References In ASP.NET Core 2.0

Problem

How to prevent insecure direct object reference in ASP.NET Core.

Solution

Create an empty project and update the Startup class.

Create a model.

Create a controller and inject IDataProtectionProvider as dependency.

Add a method that retrieves the data and then, encrypt the object reference (Id property here).

Add a method that receives the encrypted object reference and then decrypts it.

Running the sample (browsing to /movies) with show encrypted references.



Discussion

OWASP 2013 classifies Insecure Direct Object Reference as one of the top 10 risks and is present if the object references (e.g. primary key of a database record) can be manipulated for malicious attacks.

One possible method to prevent is shown in the example above, i.e. by encrypting the internal references we can hide the internal details of our database/application structure. We can encrypt in various ways, here I am using the new Data Protection API in ASP.NET Core.

Data Protection API

There are two key abstractions we utilize to encrypt the data, IDataProtectionProvider and IDataProtector. We use the provider to create a protector by calling its CreateProtector() method. This method takes in a string key (known as Purpose String). Once we have a protector, we can use the Protect() method to encrypt and the Unprotect() method to decrypt the data.

Purpose Strings

It’s a key that ensures isolation between different protectors (cryptographic consumers) i.e. data encrypted by protector A cannot be read by a protector B, as long as they use different purpose strings.

Exception

Trying to decrypt the data that has been modified will throw CryptographicException,



Limited Lifetime

You could also encrypt data that can be decrypted for only a limited period of time (e.g. creating tokens for password reset link). In order to achieve this, we use ITimeLimitedDataProtector and specify a time period when protecting the data,

Trying to decrypt the data after it’s expiry will throw CryptographicException,



Tip - Action Filter

You could create an action filter that decrypts the incoming encrypted reference, this can be reused across your application.

A simple filter (note I am using typed filter as it has dependency injection).

Configuration

You could configure the data protection API when configuring its service.

Here I am configuring,

  • Application name e.g. in order to have multiple projects in my application (e.g. APIs) decrypt the data.
  • Location where keys are stored
  • A lifetime of keys. The default is 90 days and minimum being 7 days.
  • Cryptographic algorithm: just resetting to default explicitly for demonstration purposes.
Source Code