Assert Safely: How to use .Net's Assert wisely

Paladion
By Paladion

February 15, 2006

.NET's Code Access Security is a powerful mechanism to ensure that your code is protected from malicious assemblies. In this article, we show you how to use a powerful feature of .NET securely: the assert security action.

Assert Yourself!

.NET's Code Access Security is a powerful mechanism to ensure that your code is protected from malicious assemblies. In this article, we show you how to use a powerful feature of .NET securely: the assert security action.

Of Demands and Stack Walks

First, some background. .NET maintains security by requiring all assemblies to have appropriate permissions to accessing resources. When an assembly calls a .NET framework class or any other class, the class being called may ask .NET to verify that the calling assembly has the required permissions to access it. That’s called a demand.

Verifying just the calling assembly’s permissions, however, is not enough. The call may have originated from some other assembly and may have reached the calling class after multiple hops.  .NET can maintain a secure environment only if it’s sure that all of them have the required permissions too, that none of them are malicious assembly. So .NET will have to verify the permissions of all the assemblies along the call chain. This process is called a Stack Walk.

To take an example –say assembly C calls assembly B that calls assembly A to perform a file I/O operation. The I/O class may demand appropriate file I/O permissions of A. What happens if permissions of all calling classes are not checked? If a malicious assembly X without file I/O permissions wants to perform a file I/O task, it can make a call to assembly A which will then do the file I/O job for X. To avoid such security issues, .NET goes through the stack and checks the permissions of each calling assembly.

Asserts

Asserts in .NET

Obviously a Stack Walk is an expensive process: performance and throughput get hit. An assembly can make an Assert call and stop the Stack Walk. When an assembly asserts a certain set of permissions while trying to perform a task, .NET aborts the Stack Walk and lets the operation execute.

Can any malicious assembly wanting to access a restricted resource assert the required permissions and go ahead with its operations? No, .NET has built in a certain level of security by enforcing that an assembly can call an assert only if it has those same permissions it is asserting in the first place and also a special permission required to make an assert.

But what about the permissions of the caller assemblies? What if one of them doesn’t have the permissions? Calling an assert is equivalent to saying that the asserting assembly is sure that its callers are responsible and it is ready to vouch for them. Thus, although assert helps performance it opens up a security threat – use a lot of caution when asserting on behalf of your callers. Performance alone is not a good reason to call an assert.

Here’s one place you might really need to do an assert. Say you are a component developer and need to make a native Win32 API call to open a specific type of dialog box for your clients; your assembly then needs to have the UnmanagedCodeSecurity permission – a very powerful permission. Not only your component but all its callers also need the UnmanagedCodeSecurity permission, remember, .NET does a Stack Walk to verify all callers above it. Now the UnmanagedCodeSecurity permission is not handed out to everyone, and it is unlikely that your callers are going to have it. So then what do you do? To move forward, you are forced. You have to assert that permission on behalf of your callers. Not a perfect situation, but necessary to go forward.

In such cases, should you assert unconditionally? Here’s the best practice for such situations: if you have to assert on behalf of your callers, then demand adequate permissions of your callers, in turn. Thus, if you have to assert the UnmanagedCodeSecurity permission in the example above, demand that your callers have the permission to work with the UI at least.

Asserts

That ensures that when you assert a powerful right on behalf of your callers, you are sure that the callers have adequate permissions for a closely related activity.

public static void DisplayCustomDialog(string text,string caption) {
IStackWalk stackWalker;
stackWalker = new SecurityPermission(SecurityPermissionFlag.
UnmanagedCode);
stackWalker.Assert();
IPermission permission;
permission = new UIPermission(UIPermissionWindow.SafeSubWindows);
permission.Demand();
}

The code snippet below shows the principle in action. DisplayCustomDialog asserts the UnmanagedCode permission, but follows it up with a demand for the UI Permission.

The Secure coding guideline is: “When asserting on behalf of your callers, demand that your callers have adequate permissions.

References


Tags: Technical

About

Paladion