ADO.NET 2.0 Security Guidelines - Authorization

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Chaitanya Bijwe


Contents

Restrict Unauthorized Callers

Application code should authorize a user based on a role or identity before the application allows the user to connect to the database. Ideally, role checks should be performed in the business logic layer. For additional protection, data access code can perform authorization by using a variety of techniques, including those outlined below.

You can use principal permission demands on data access methods when you want method-level authorization. The following attribute ensures that only users who are members of the Manager role can call the GetCustomerDetails method.

using System.Security.Permissions;
...
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Manager")]
public void GetCustomerDetails(int CustId)
{
}
 

If finer granularity is required and authorization needs to be performed within a method, then you can perform imperative principal permission demands or explicit role checks on a block of code. The following code example shows how to perform an imperative principal permission demand.

using System.Security;
using System.Security.Permissions;
public void GetCustomerDetails(int CustId)
{
 try
 {
   // Imperative principal permission role check to verify
   // that the caller is a manager
   PrincipalPermission principalPerm = new PrincipalPermission(null, "Manager");
   principalPerm.Demand();
   // Code that follows is only executed if the caller is a
   // member of the "Manager" role
 }
 catch( SecurityException ex )
 {
  . . .
 }
}
 

The following code example uses explicit role checks.

public void GetCustomerDetails(int CustId)
{
 if(!Thread.CurrentPrincipal.IsInRole("Manager"))
 {
   . . .
 }
}
 

Restrict Unauthorized Code

Ensuring that only trusted code can access your data access classes and methods decreases the risk that malicious code can exploit your application.

To restrict access to your code, do the following:

  • Design for restricted access.
  • Place ASP.NET data access code in your application's Bin directory.
  • Use strong names for data access library code.

Design for Restricted Access

Carefully design the public interfaces, classes, and methods exposed by your data access code. Make sure that code which is for internal use by the data access library is marked private. When designing for restricted access, consider the following guidelines:

Consider creational patterns, such as Abstract Factory or Singleton, to help make sure that the data access library retains control over how its objects are instantiated. Having the factory return an interface also ensures that the actual class remains hidden from the outside. If you expose extension points through a provider model to provide the use with the ability to implement an interface or extend a class, make sure that the extension class has restricted access to the underlying data access code. Mark classes and methods that need not be accessed outside the data access block as internal. Seal classes that need to be exposed but should not be inherited from. Mark methods that do not need to be exposed as private or internal.

Place ASP.NET Data Access Code in Your Application's Bin Directory

If you are developing data access code for exclusive use by a single ASP.NET application, place the data access assembly in your application's Bin directory. To restrict access to the assembly, configure an ACL for the Bin directory that provides only read access to your application's unique process identity.

Use Strong Names for Data Access Library Code

Data access library code that is to be used by more than one application should be strong name signed and added to the global assembly cache. The added benefit of strong naming your library code is that the common language runtime prevents partially trusted code from calling a strong named assembly by adding a link demand for the FullTrust permission set.

Restrict Application Access to the Database

Your application should connect to the database by using a least-privileged account. This limits the damage that can be done in the event of a SQL injection attack or in the event of an attacker obtaining your account's credentials. With Windows authentication, use a least-privileged account with limited operating system permissions and limited ability to access Windows resources. Regardless of the authentication mechanism, restrict the account's permissions in the database.

Use the following process to limit permissions in the database:

  1. Create a SQL Server login for the account.
  2. Map the login to a database user in the required database.
  3. Place the database user in a database role.
  4. Grant the database role limited permissions to only those stored procedures or tables that your application needs to access.

Unless there are specific reasons otherwise, the application should not be authorized to perform create, retrieve, update, and destroy/delete operations directly on any table. Instead, limit access to selected stored procedures only. If you must grant table access, grant the minimum access that the application requires.

By using a database role, you avoid granting permissions directly to a database user. This isolates you from potential changes to the database user name. For example, if you change the database user name, you can simply add the new user to the database role and remove the existing one.

Personal tools