.NET Framework Security Basics (C# and Visual Basic)

Code access security is the part of the .NET Framework that controls access to resources by controlling the execution of code. This security feature is separate from, and in addition to, the security provided by the operating system.

Note

In .NET Framework 4, security transparency is the default enforcement mechanism. Security transparency separates code that runs as part of the application from code that runs as part of the infrastructure. For more information, see Security-Transparent Code.

Important

There are major differences between the code access security system in .NET Framework 4 and that of earlier versions. Security policy is no longer applied to applications. All applications that can be run from the desktop are now executed as full-trust applications. This includes applications on the computer and applications that can be run from a network share. Partially trusted applications must be run in a sandbox, which determines their grant set. The permission system continues to be used, but it is transcended by security transparency rules. For information about these changes, see Security Changes in the .NET Framework 4.

How It Works

When a user runs your application, it is assigned to a zone by the .NET Framework common language runtime. The five zones are:

Zone

Description

My Computer

The application code resides on on the user's computer.

Local Intranet

The application code runs from a file share on the user's intranet.

Internet

The application code runs from the Internet.

Trusted Sites

These are applications from sites defined as "Trusted" through Internet Explorer.

Untrusted Sites

These are applications from sites defined as "Restricted" through Internet Explorer.

The assignment of the first three zones, My Computer, Local Intranet, and Internet, is based on where the code is located. You can override the assignment by assigning specific sites to the Trusted Sites or Untrusted Sites groups in the Internet Explorer.

Each of these zones has specific access permissions set by a system administrator. The security level for a zone may be set to full trust, medium trust, low trust, or no trust. The trust levels define the resources that are accessible to the application. The zone, together with other security evidence, such as the publisher, strong name, Web site, and URL of the code, determines the permissions that are granted to the code at run time. (For more information about security evidence, see Evidence.) You have no control over the security settings on the user's computer, yet your application must work within the settings it encounters as it runs. This may mean that your application will be denied access to particular resources. For example, your application may need to write data to a file, yet the user's system will deny write access at run time by raising an exception.

Your job is to develop your application to handle this situation. This does not necessarily mean that you will make your application find another way to write the data. It does mean that your application needs to anticipate that it may not be able to write the data and then respond to such a possibility. You may want to use more exception handling or some of the objects in the System.Security.Permissions namespace to make your code more robust. A brief description of these methods is included in a later section of this article, "Developing for Partial-Trust Environments."

The security levels for zones are set using the Administration Tools installed when the .NET Framework is installed. To learn more about the setting security levels for zones on a computer, see Administration Tools.

Full Trust

Developers often work in a full-trust environment. They keep their source code on their hard drives, and they test their applications from their development computers. In this full-trust environment, any code the developer compiles is allowed to run on the local computer. Security exceptions do not surface, because the local computer is defined to be a full-trust environment by default.

Partial Trust

Partial trust describes any zone that is not a full trust zone. When an application is deployed, it may move into a new zone, perhaps one that does not grant full trust to the application. The two most common scenarios that run code in partial trust are:

  • Running code that is downloaded from the Internet.

  • Running code that resides on a network share (intranet).

Some examples of resources that might be denied in a partial-trust zone are:

  • File I/O operations, including reading, writing, creating, deleting, or printing files.

  • System components, such as registry values and environment variables.

  • Server components, including directory services, registry, event logs, performance counters, and message queues.

What is not allowed in partial trust? That is not easy to determine. Each class and each method of each class in the .NET Framework has a security attribute that defines the level of trust needed to run that method, and that attribute may not be accessible at run time because of just these security features. The zone level is not a simple mapping of trust level to attributes, but is a collection of particular permissions given to particular classes and methods. Your application will not be able to simply query for the trust level and then be able to predict which resources are not available. You can determine whether or not your application is running in full trust. One method of doing so is described in the next section, "Developing for Partial Trust Environments."

Developing for Partial-Trust Environments

This section presents a very brief look into how security concerns might affect the code you write. There is no single solution to developing for the partial-trust environment. Your solution will depend on the application you are writing. Additionally, because the trust level may change during execution of your application, you cannot simply test for the existing trust level and then proceed.

Security Exception Code

The first step in developing for partial-trust zones is to write code that recognizes that security exceptions will surface. Consider the following code:

Public Sub MakeABitmap()
    Dim b As New System.Drawing.Bitmap(100, 100)
    ' Some code here to draw a nice picture in the bitmap
    b.Save("c:\PrettyPicture.bmp")
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b =
        new System.Drawing.Bitmap(100, 100);
    // Some code here to draw a nice picture in the bitmap
    b.Save("c:\\PrettyPicture.bmp");
}

This method runs without throwing an exception if the project and the project assembly are stored on the hard disk of your computer, and if you are a member of the Administrators group on your computer. If you deploy this application to your intranet, SecurityException may be thrown when the application attempts to save the bitmap object. If you do not have a Try...Catch...Finally Statement (Visual Basic) or try-catch-finally (C# Reference) block around this code, your application terminates with the exception. This is probably not a satisfactory user experience. If you add exception-handling code, then your application can:

  • Warn the user that the application cannot complete all the tasks it needs to.

  • Clean up any existing objects, so that code that runs after the catch block does not fail.

You could modify the bitmap-saving code as shown below. The added code warns the user that that file was not saved because of a security denial, and it separates security failures from other file I/O failures, such as incorrect file names. This method does not create any security holes. The user will either modify security to trust your application, or the application will not run.

Public Sub MakeABitmap()
    Dim b As System.Drawing.Bitmap = Nothing
    Try
        b = New System.Drawing.Bitmap(100, 100)
        b.Save("c:\PrettyPicture.bmp")
    Catch ex As System.Security.SecurityException
        ' Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " & 
               "and the bitmap was not saved.")
    Catch ex As System.Exception
        ' React to other exceptions here.
        MessageBox.Show("Unable to create and save the bitmap.")
    End Try
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b = null;

    try
    {
        b = new System.Drawing.Bitmap(100, 100);
        b.Save("c:\\PrettyPicture.bmp");
    }
    catch (System.Security.SecurityException ex)
    {
        // Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " +
            "and the bitmap was not saved.");
    }
    catch (System.Exception ex)
    {
        // React to other exceptions here.
        MessageBox.Show("Unable to create and save the bitmap.");
    }
}

You can specifically ask for permissions from the runtime, shown below using the Demand method. The runtime may then grant or deny the demand. The demand is denied by raising a security exception. You might rewrite the code like this to explicitly demand permission to write the bitmap file:

Public Sub MakeABitmap()
    Dim b As System.Drawing.Bitmap = Nothing
    Dim filename = "c:\PrettyPicture.bmp"
    Dim permission As New System.Security.Permissions.FileIOPermission( 
        System.Security.Permissions.FileIOPermissionAccess.Write, 
        filename)

    Try
        permission.Demand()
        Try
            b = New System.Drawing.Bitmap(100, 100)
            b.Save(filename)
        Catch ex As System.Exception
            MessageBox.Show("Unable to create and save the bitmap.")
        End Try
    Catch ex As System.Security.SecurityException
        ' Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " & 
               "and the bitmap was not saved.")
    Catch ex As System.Exception
        ' React to other exceptions here.
        MessageBox.Show("Other error.")
    End Try
End Sub
public void MakeABitmap()
{
    System.Drawing.Bitmap b = null;
    string filename = "c:\\PrettyPicture.bmp";

    System.Security.Permissions.FileIOPermission permission;
    permission = new System.Security.Permissions.FileIOPermission(
        System.Security.Permissions.FileIOPermissionAccess.Write, filename);

    try
    {
        permission.Demand();
        try
        {
            b = new System.Drawing.Bitmap(100, 100);
            b.Save(filename);
        }
        catch (System.Exception ex)
        {
            MessageBox.Show("Unable to create and save the bitmap.");
        }
    }
    catch (System.Security.SecurityException ex)
    {
        // Let the user know the save won't work. 
        MessageBox.Show("Permission to save the file was denied, " +
               "and the bitmap was not saved.");
    }
    catch (System.Exception ex)
    {
        // React to other exceptions here.
        MessageBox.Show("Other error.");
    }
}

Testing

The second step in developing for partial-trust zones is testing in multiple environments, especially from your intranet and the Internet. This will force the security exceptions to be thrown. One important test is to create a user account on your local computer that does not have Administrator rights and try running your application with that account.

See Also

Tasks

How to: Run Partially Trusted Code in a Sandbox

Concepts

Security Changes in the .NET Framework 4

Other Resources

Code Access Security

Secure Coding Guidelines

Key Security Concepts