Development-Time Security Considerations

for RuBoard

The security features within the .NET Framework were designed, in part, to make it much easier for developers to write secure code. When authoring code, developers need to consider two main factors ”the security requirements of the assemblies they are authoring and the sensitive resources and data (if any) that are potentially exposed by their classes to other code. The two factors are related but distinct, and it is slightly easier to understand the relationship between them if we begin with a discussion of the second factor, protecting sensitive resources, and then go back to investigate how developers indicate and declare security requirements of their assemblies.

The first security-related action a developer must perform when beginning work on a new assembly is to determine whether the assembly will expose any sensitive resources through its classes and methods? That is, will the classes and methods within the assembly expose sensitive resources to callers of those methods. If the answer to this question is yes, the assembly must be a secure assembly. Secure assemblies are discussed in detail in Chapter 24, "Architecting a Secure Assembly," Chapter 25, "Implementing a Secure Assembly," and Chapter 26, "Testing a Secured Assembly," but the basic issue is this ”if the assembly you are authoring is going to make a new sensitive resource available to semitrusted code, your assembly must perform appropriate security checks within each method that provides access to or operates on the sensitive resource. Essentially, your new assembly is going to be a gatekeeper or guard of the protected resource, and you must treat every request for access to the resource with an appropriate degree of caution.

How do you determine whether your new assembly must be a secure assembly? This basic determination revolves around the list of resources exposed by your assembly to other code and whether those resources are sensitive or already protected. Consider the following scenario. Suppose that you want to write a method that will write a message (we'll use "Hello, World!" for historical reasons) to a file named hello.txt located on the C: drive of the computer. Using the .NET Framework, your code might look as shown in Listing 12.1. This program creates a FileStream object mapped to the C:\hello.txt file on the hard disk (creating the file if necessary) and writes the string "Hello, World!" to that file.

Listing 12.1 Sample Hello, World! Program
 using System; using System.IO; public class HelloWorld {   public static void Main(string[] args) {     FileStream fs = new FileStream("C:\hello.txt", FileMode.OpenOrCreate, FileAccess. graphics/ccc.gif Write);     StreamWriter sw = new StreamWriter(fs);     sw.Write("Hello, World!");     sw.Close();   } } 

Does the program in Listing 12.1 constitute a secure assembly? That is, does this simple program require the addition of any security checks or permission demands? The answer is "No, it does not," because the program, by itself, does not expose any new sensitive resources. The only resource that is used or modified by the HelloWorld program is the c:\hello.txt file that is associated with the FileStream fs , and the FileStream class itself performs the necessary security checks to determine whether callers of its methods (including the HelloWorld program) should be granted access to the file system objects that it exposes.

The class libraries that make up the .NET Framework are secure assemblies; they implement appropriate security checks, in the form of permission demands, for the resources that they expose. Every sensitive resource that is made available to semitrusted code through the .NET Framework class library is protected by demands for a related security permission. For example, the constructors on the FileStream class demand instances of the FileIOPermission before returning any instances of the class. Similarly, the registry-related classes demand instances of RegistryPermission , and the network-related classes demand instances of SocketPermission , WebPermission , or DNSPermission as appropriate to their function. This is one of the great advantages of writing a program on top of the .NET Framework; if all the resources that you use in your programs are already protected by appropriate permission demands, you do not need to add additional security checks to your own code. Because the HelloWorld program in Listing 12.1 only uses resources that are exposed through the class libraries of the .NET Framework, no additional security checks need to be made in our code.

NOTE

Even if your assembly does not expose any sensitive resources, if it performs any operations that affect the normal behavior of the .NET Framework security system, it must be a secure assembly. For example, if a method in your assembly calls the Assert() method on a permission, that modifies the behavior of the security stack walks and your assembly should be secure. Similarly, if you ever suppress the runtime security check that normally occurs when using platform invoke or COM interoperability via the SuppressUnmanagedCodeSecurityAttribute attribute, your assembly needs to be secure.


Even though our HelloWorld program does not expose any sensitive resources that require protection, it does make use of a protected resource ”namely, the FileStream object that represents the c:\hello.txt file. Our program will only run successfully at execution time if it is granted sufficient access rights to write to the c:\hello.txt file. We can indicate this security requirement for our assembly to run through the use of assembly-level declarative permission requests . Declarative security attributes in general were introduced briefly in Chapter 6, "Permissions: The Workhorse of Code Access Security," and assembly-level requests are discussed in detail in Chapter 29, "Writing a Semitrusted Application." Basically, declarative security attributes are a mechanism for communicating assembly permission requirements to the policy system. Referring back to Listing 12.1, because HelloWorld will only operate correctly if it is granted write access to the c:\hello.txt file, we can indicate this requirement by adding the following assembly attribute to our source code:

 [assembly:System.Security.Permissions.FileIOPermission( System.Security.Permissions. graphics/ccc.gif SecurityAction.RequestMinimum, Write="C:\hello.txt")] 

This attribute indicates that a minimum grant of the FileIOPermission , including write access to c:\hello.txt , is required for the program to run. See Chapter 29 for a complete description of the syntax and proper use of assembly-level security permission requests.

CAUTION

If you determine that your assembly will be exposing a sensitive resource, you must secure that access with appropriate permission demands. Chapters 24 through 26 describe in detail how to architect, implement, and test a secured assembly.


NOTE

There is a subtle interaction that occurs between the Runtime and your source code compiler when you use declarative security attributes within your programs. At compile time, declarative security attributes are checked for correctness by the version of the Runtime installed with your compiler and converted into a different formation before being embedded in the metadata of the output module or assembly.


The final important security-related decision that you must make at code authoring time is whether you want your assembly to have a strong name . As discussed in Chapter 9, "Understanding the Concepts of Strong Naming Assemblies," strong names are cryptographically protected names for assemblies. Strong names are built on top of public key cryptography. Strong names are used by the CLR to provide both integrity protection for your assemblies as well as cryptographically strong binding among assemblies. See Chapter 25 for a description on how to use the strong name tool (Sn.exe) distributed with the .NET Framework SDK to create strong name key pairs and how to build strong names into your assemblies using the AssemblyKeyFile , AssemblyKeyName , and AssemblyDelaySign assembly-level custom attributes.

NOTE

We recommend that all developers take advantage of the strong name features of the CLR and digitally sign their assemblies with strong names. Only strongly named assemblies can be added to the Global Assembly Cache, and strong names provide a very high degree of protection against accidental or malicious tampering with your assemblies. Also, version checking and side-by-side execution are only available for strongly named assemblies. Note that once you strong name your assembly, you will have to annotate it with the AllowPartiallyTrustedCallersAttribute if you want it to be callable from semitrusted assemblies. (See Chapter 25 for a detailed discussion of the AllowPartiallyTrustedCallersAttribute .)


for RuBoard


. NET Framework Security
.NET Framework Security
ISBN: 067232184X
EAN: 2147483647
Year: 2000
Pages: 235

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net