.NET 2.0 Security Guidelines - Class Design Considerations

From Guidance Share

Jump to: navigation, search

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

Contents

Restrict class and member visibility

Class and member access modifiers allow you to restrict the callers of your code. The fewer entry points (public interfaces) you have in your code, the smaller your attack surface is and the easier it is to protect.

Use the most restrictive access modifier possible for your code. Use the private access modifier wherever possible. Use the protected access modifier only if the member should be accessible to derived classes. Use the internal access modifier only if the member should be accessible to other classes in the same assembly.

Note Access modifiers are enforced at compile time only. When malicious code runs in a full trust environment, it could use reflection or unmanaged pointers to bypass these visibility restrictions.


Consider using the sealed keyword

You can use the sealed keyword at the class and method level. In Visual Basic .NET, you can use the NotInheritable keyword at the class level or NotOverridable at the method level. If you do not want anyone to extend your base classes, you should mark them with the sealed keyword.

Before you use the sealed keyword at the class level, you should carefully evaluate your extensibility requirements. It is especially important to seal a class in the following situations:

  • The class contains security secrets, such as passwords, that are accessible through protected APIs.
  • The class contains many virtual members that cannot be sealed, and the type is not designed for third-party extensibility.

You can also seal individual methods and properties within a class. For example, if you derive from a base class that has virtual members and you do not want anyone to extend the functionality of the derived class, you can consider sealing the virtual members in the derived class. Sealing the virtual methods has performance benefits because it makes them candidates for inlining and other compiler optimizations.

Consider the following example.

public class MyClass{ 
 protected virtual void SomeMethod() { ... } 
}
 

You can override and seal the method in a derived class, as follows.

public class DerivedClass : MyClass { 
 protected override sealed void SomeMethod () { ... } 
}
 

This code ends the chain of virtual overrides and makes DerivedClass.SomeMethod a candidate for inlining.

Note Class sealing is enforced at compile time only. When malicious code runs in a full trust environment, it could use reflection or unmanaged pointers to bypass this restriction.


Restrict access to your code

Not all methods in a class are meant to be accessed by all code. In some cases, you might need to restrict methods that are are not intended for general public use, but must still be marked as public. For example, you might expose public methods that need to be accessed by specific assemblies developed by your organization, but are not intended to be accessed by others. Consider the following approaches to restricting access to your code:

  • Strong name your assembly, so that partially trusted callers cannot call into it.
  • Restrict callers of your code by demanding specific or custom code access security permissions.


Do not trust input

Do not trust any input to your application. Validate and constrain input by checking it for type, length, format, and range.

An attacker who passes malicious input can attempt SQL injection, cross-site scripting, and other injection attacks that aim to exploit your application's vulnerabilities.

Check for known good data and constrain input by validating it for type, length, format, and range. Check all numeric fields for type and range. You can use regular expressions and the Regex class, and you can validate numeric ranges by converting the input value to an integer or double, and then performing a range check.


Use properties to expose fields

Fields should not be exposed directly to calling code. Properties allow you to add additional constraints, such as input validation or permission demands.

Mark fields as private, and create read/write or read-only properties to access them.

Note Private fields are enforced at compile time only. When malicious code runs in a full trust environment, it could use reflection or unmanaged pointers to bypass these visibility restrictions

Use read-only fields appropriately

Do not expose your fields to caller modification unless absolutely necessary. Mark properties read-only unless the caller needs to be able to make a modification. This prevents a caller from accidentally modifying a field.

Note Read-only properties are enforced at compile time only. When malicious code runs in a full trust environment, it could use reflection or unmanaged pointers to bypass these visibility restrictions.


Use private default constructors to prevent unwanted object instantiation

A class with a public constructor can be instantiated. Mark the class's constructor private if it is not designed to be instantiated. An example of a class that is not designed for instantiation is a one that contains only static methods and properties.

Note Private constructors are enforced at compile time only. When malicious code runs in a full trust environment, it could use reflection or unmanaged pointers to bypass these visibility restrictions.

Personal tools