Wednesday, September 17, 2008

Security implementation tips

How do you implement security in your ASP.NET application?

I propose to use AOP and interceptors. Short sample.

You have business logic methods like:

public List<Action> GetActions();
public void ExecuteAction(Action action, object data);


And you don't care about security there. You just do your job: create list of all supported actions and return it in GetActions and execute any supported actions in ExecuteAction. Smart, clear and straightforward.

But where is security? In interceptors.

You create interceptor that wraps these two methods. These interceptor knows about allowed actions and has access to such list of actions.

On every execute of GetActions it intersects List of returned actions with list of allowed actions and returns the result of intersection.

On every execute of ExecuteAction it checks whether action is allowed or not.

So you:
1. Have separate security mechanism that works independently.
2. Do not care about security during business logic development.
3. Can split these tasks and divide them between different people.
4. Can use other tips mentioned below :)


And few more tips with security:

1. Always try to separate logic from security as much as possible. This allows you to separate concerns, divide work and allows developers to concentrate on their narrow task.

2. Add possibility to switch off the security. Sometimes it's necessary to test if error occurred because of business logic failure or security failure. It's hard to do if there is no possibility to switch off security. It's not a hard task but it could save time during testing and stabilization.

3. Remove possibility to switch off security from production version. There is a risk that somebody could change your configuration parameter directly or indirectly and in such way perform leverage privileges attack. To avoid this, remove security switch off from production code. But do not delete code! Just use the following:


private bool IsSecurityEnabled
{
    get
    {
#if DEBUG
        return Configuration.IsSecurityEnabled;
#else
        return true;
#endif
    }
}

4. Avoid possibility to delete last administrator. To prevent system from being "unadministrable" add code that will check all delete operation on subject of is there any administrators in the system or last one is deleted. Or select one "Super Administrator" that could be removed from the system.

5. Make security as fast as possible. Create User permissions tickets to save all user allowed actions, cache actions etc. Security should be quick because may be used often.

6. Check security on business logic level. Do not rely on GUI. On UI level you should concentrate on UI as much as possible and do not make security checks where allowed. Or GUI could be even compromised, or UI developer could forget to exclude operation from UI. Moreover, later customer could ask you to write another client based on current application logic level.


To be continued... :)

kick it on DotNetKicks.com




Share this Post:

Facebook


Digg


DelIcioUs

2 comments:

Greg Beech said...

A much better approach is to use a custom IPrincipal along with custom CAS attribute, and then use the attribute to annotate your methods. This takes advantage of the built-in security mechanisms which makes it easy to understand, and means you don't have to mess around with delegates or interception because the framework does this for you.

AlCor said...

I'm disagree with you for several reasons:
1. CAS is impossible to implement here: yes, you can try to reject access to ExecuteAction methods, but how do you implement CAS for GetActions method? It should return right actions based on Role-based security.
2. CAS is slower then Intercepting with IL code generation.