Tip

Discover the power of .NET's code access security

I recently came across a security issue while reviewing a client's .NET application. It is an interesting story because it demonstrates the power of .NET's code access security and Link Demand specifically.

The application spans multiple assemblies and has a database that contains a lot of important information. To avoid redundant code for database access, the client designated one assembly as the data access assembly. All other assemblies have to go through this data access assembly to get data from the database. This, however, does not assure us of the quality of the input reaching the data access assembly.

The developers had a nice solution for this problem. They placed a validation assembly between the data access assembly and the other client assemblies. All client assemblies go through this validation assembly to reach the data access assembly.

In the above diagram, the four client assemblies go through the validation assembly to reach the data access assembly. That seems to be a nice architecture. Doesn't it? Only good input reaches the data access layer, since all clients go through the validation assembly, and the validation assembly rejects bad input. It works as long as there are no bad assemblies around.

Enter the "bad guy." The bad guy is a malicious assembly -- written by somebody else but running on the same machine -- interested in accessing the database. Notice

    Requires Free Membership to View

that the bad guy can bypass the validations and directly call the data access layer. This is a security issue that the developers didn't think of. Now they wanted a solution for it.

How do we prevent this? The solution is to use Link Demand with Strong Names.

Link Demand to the rescue
First, some background: When an assembly requests a Link Demand for some permissions, .NET will verify that the calling assembly has the demanded permissions at link time. Note the Link Demand checks only the permissions of the immediate caller, and it's done at link time.

A Strong Name is a .NET feature that allows assemblies to have unique, cryptographically secure names. You can trust the source and name of a strongly named assembly, as it's signed with a public/private key pair that belongs to the developer.

The private key in the pair is a secret known only to the developer or his organization. The interesting thing is that a Strong Name can be used as an evidence for a permission that's being demanded. To use Strong Names in demands, .NET defines a permission class called StrongNameIdentityPermission. That permission class can be used to declaratively invoke demands with Strong Names.

In our solution, we want the data access assembly to perform a Link Demand to restrict the caller. Now the Link Demand has to be on some evidence that the caller assembly can provide. We could do a Link Demand on the public key of the organization. Since the public keys would be unique to the organization, we can ensure that only assemblies belonging to the organization can call the data access assembly. Here's what the Link Demand would look like:

[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey = PublicKeys.MyCompany)]
.NET security features

User management and login security controls in ASP.NET

Learning guide: Developing secure .NET applications 

Book excerpt: Security in the .NET Framework 2.0

The above would ensure that only assemblies belonging to the same organization (whose public key is PublicKeys.MyCompany) can invoke the Data access assembly.

That looks good to me.

But you might feel that is too lenient considering that the design requires only the validation assembly to call the data access assembly. I think it is OK to trust assemblies of one's own organization and rest assured that they will not indulge in malicious activities. But if you want to be absolutely sure, you need to ensure only the specific assembly that is granted access. That can be done by demanding on the name in addition to the public key of the assembly.

[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey = PublicKeys.MyCompany)]
[StrongNameIdentityPermission(SecurityAction.LinkDemand, name = "ValidationAssemblyName")]

The above ensures that only the validation assembly can call the data access assembly. That's very secure.

Some of you might feel that even the first option of trusting only the organization's own assemblies is too strict. There could be real situations when we trust some external assemblies enough to let them call the data access assembly. So how can we allow assemblies belonging to certain trusted vendors also to call the data access assembly?

Link Demand comes to our aid again. What we would like is to have .NET check for a set of allowed public keys. The regular Link Demand we have seen so far can demand only a single public key. There's a slightly different version of Link Demand, called LinkDemandChoice that supports multiple public keys. We can use LinkDemandChoice in this situation.

[StrongNameIdentityPermission(SecurityAction.LinkDemandChoice, PublicKey = PublicKeys.Vendor1)]
[StrongNameIdentityPermission(SecurityAction.LinkDemandChoice, PublicKey = PublicKeys.Vendor2)]

Using the above we can restrict which external vendors may call the Data access assembly.


  Link Demand

  • Link Demand verifies permissions during link time.
  • Only the immediate caller's permissions are verified.
  • Use LinkDemand on public key to restrict access to a specific vendor.
  • Use LinkDemand on name/public key to restrict access to one assembly.
  • Use LinkDemandChoice with public keys to allow multiple trusted vendors to access a restricted assembly.

-------------------------------------
About the author: Sangita Pakala, GCIH, is the lead author of the popular "OWASP Application Security FAQ. Sangita's work has been presented at RSA Conference 2006 and ISACA Europe 2005. She is the delivery manager at Plynt and also the editor of Palisade, the application security magazine.


This was first published in June 2006

There are Comments. Add yours.

 
TIP: Want to include a code block in your comment? Use <pre> or <code> tags around the desired text. Ex: <code>insert code</code>

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
Sort by: OldestNewest

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.