Abstract

Security is an essential part of .NET applications and should be taken into consideration from the grass root level. Security is all about protecting your assets from unauthorized actions. Code Access Security a concept of .NET framework introduced to Windows enables you to control the permissions that individual application have. As a developer, you must understand how to create applications that work even when some permission is restricted. You can also use CAS to improve your applications’ security by restricting which callers can use your code and forcibly limiting your application to a restricted permission set. This article looks through the features available in .NET to help you manage security, including how .NET protects you from malicious code, how to administer security policies, and how to access the security subsystems programmatically. The second concern of this article is about the users who use the resources on your system and on the network. They should pay attention to what are and are not supposed to do. To address these issues, .NET provides us concrete security solutions with array of techniques such as code base security, role base security, authentication, verification, and authorization.

Security Modal

When you perform some action on the user interface such clicking a button, your application connects to the Internet, downloads the modules into the Download Assembly Cache, and begins executing. Behind the scenes, what evidence do you actually have that you can trust the code your computer is downloading? How do you know that the module you requested is, in fact, the one you are receiving?

.NET enforces the security polices around assemblies. It uses the evidence that the particular assembly having such as the origination of the file, which is discussed later in more granular form. The runtime places all codes from local intranet into a specific group. It then uses the security policies to decide what permissions the code should be granted at a granular level. All code automatically runs behind the scenes within the security context of the CLR.

MSIL Verification

When a piece of .NET code is code is compiled, the output produces an intermediate code that needs a run time to execute it. This intermediate code is called MSIL code. When loading the assembly by runtime, it first validates the metadata, which is type information about interface, or the assembly to see that it is well formed. It then examines the MSIL code against this metadata to see that the code is type safe. When MSIL code needed is to execute, it is compiled Just-in-Time and converted into a platform specific code that’s called native code.

Thus, any code that can be converted to native code is valid code. Code that can’t be converted to native code due to unrecognized instructions is called “invalid code.” During JIT compilation the code is verified to see if it is type-safe or not.

To determine whether your code is verifiable type safe, you can use this PEVerify utility at the .NET command prompt as following:

peverify ConsoleApplication1.exe

After executing the aforementioned command, you will get the following output as following:

All classes and Methods in ConsoleApplication1.exe Verified

Code Access Security

Code Access Security enables users to restrict on a very granular level what managed code can do according to your level of trust. If the CLR trusts the code enough to allow it to run, it will begin executing the code depending on the permissions given to the assembly. If the code is not trusted and attempts to perform some actions for which it does not have relevant rights, a security exception is thrown. It is important to understand that code access security is about protecting resources such as logs, printer, local drive, user interface and network from malicious code. It is not primarily a tool for protecting software from users. Unfortunately, Code Access Security can be applied only to manage code applications that use the .NET Framework runtime. Unmanaged applications run without any CAS restrictions and are limited only by the operating system’s role base security. If CAS is used to restrict the permissions of an assembly, the assembly is considered partially trusted. Partially trusted assemblies must undergo CAS permission checks each time they access a protected resource. Fully trusted assemblies, like unmanaged code, can access any system resource that the user has permissions to access.

Elements of Code Access Security

Every security system needs a mechanism (such as user name, password and ACL) to identify the users and determine what a user can or can’t do. However CAS identifies and assigns permissions to applications rather than people. It identifies assemblies using evidence. Each element is the way that an assembly can be identified –such as location, hash code, and signature of the assembly. Evidence is the information that the runtime gathers about an assembly to determine to which code group the assembly belongs. Code groups in turn grants an assembly a permission set. There are three main components of code access security; evidence, code group and permissions.

Evidence

In order for the CLR to determine which code group to place assembly information into, the first step is to read supplied evidence. There are two main sources of information are internet and intranet. The internet group defines code that is sources from the internet and intranet group defines code sources from the LAN. The examination of the assembly evidence makes the authentication part of the security process. The following table depicts the major type of evidence an assembly can present to CLR.

Evidence Description
Zone The region such as intranet, local, trusted from which the code originated.
URL The specific URL from which the code originated.
Strong Name Unique verifiable name for the code.
Site The website from which the code originated.
Hash Value The hash value of the assembly contents.
Publisher The assembly digital signature which uniquely identified the developer.
Application Directory The directory in which assembly resides.

Code Group

The evidence provided by an assembly is used as the condition for granting and revoking permissions to it. It is done by putting the code in an appropriate code group. Every code group stipulates a membership condition and has particular conditions attached to it. Any assemblies that meet the conditions becomes a member of the group. Code groups are arranged in a hierarchy and assemblies are nearly always matched to several code group. The code group at the root of the hierarchy is called All Code and contains all other code groups.

Permissions

Permissions are the actions you allow each code group to perform. The system administrator usually manages the permissions at enterprise, machine and user levels. The CLR virtual Execution System (VES) loads and runs programs. It provides the functionality required to execute managed code and uses assembly metadata to connect modules together at runtime. When VES loads an assembly, it matches the assembly to one or more code groups. Each code group is assigned to one or more permissions that specify what actions assemblies can do in that code group.

Note: mscorcfg.msc is no more part of .NET 4.0; you can use caspol.exe instead to do the same work.

Permissions set are unique combinations of security configurations that determine what each user with access to a machine can do on that machine. There are several permission sets that ship with the .NET framework as follows in the table:

Permission Description
FullTrust Allow full access to all resources.
Everything Allow full access to all resources( group doesn’t added to assembly list)
Internet Grant Default rights.
SkipVerification Bypass all security verification
Nothing Denies all access including Execution
Execution It Allow execution-only access.

We will now create simple applications that will hard-code the name of an assembly and full path to load it into memory. At this point, we will enumerate over each supplied form of assembly evidence and print the data to the console window. To begin, the Program type provides a Main() method that allows users to enter the full path to the assembly they wish to evaluate. We will pass the Assembly reference to another helper method named DisplayEvidence(). Here is the story so far as following;

using System;
using System.Collections;
using System.Security.Policy;
using System.Reflection;

namespace SecTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Load another assembly
            Assembly asb = Assembly.LoadFrom(@"F:TemptesttestbinDebugtest.exe");

            Console.WriteLine("***** Evidence Viewer *****n");

            if (asb != null)
            {
                DisplayEvidence(asb);
            }
            Console.ReadLine();
        }

        private static void DisplayEvidence(Assembly asm)
        {
            // Get evidence collection using enumerator.
            Evidence e = asm.Evidence;
            IEnumerator obj = e.GetHostEnumerator();
            // Now print out the evidence.
            while (obj.MoveNext())
            {
                Console.WriteLine(" **** Press Enter to continue ****");
                Console.ReadLine();
                Console.WriteLine(obj.Current);
            }
        }
    }
}

To test our application, my suggestion is to create a folder directly on your C drive named Temp. Into this folder, copy the strongly-named test.exe assembly, which is just a simple program, and run your program. Your application should now print out each flavor of evidence to the console, as shown in Figure 1.1 (note that the way our application was created, you will need to hit the Enter key to display each form of evidence).


Figure 1.1

Here you can notice that test.exe has been placed into the MyComputer zone, from the URL of F:/Temp, and has a specific strong name value. If you were to load assemblies from an entirely different location (such as a remote website), you would obviously see unique output. At this point simply understand that when an assembly is loaded into memory, the CLR will investigate the supplied evidence.

Using Visual Studio to Figure Minimum Permissions

One of the most common problems faced by a programmer during testing the application security and permissions in past, is that they always forced to develop application under Full Trust. Which implies having access to the system resources in very open manner. Visual Studio IDE ships with the security configuration features. The new security tab allows you to run your applications under different types of zones as shown in the following screenshot:


Figure 1.2

After checking the Enable ClickOnce security setting check box, you will able to select whether the application will be running on the client machine under full trust or partial trust.

Managing Code Access Permissions

This section describes the most common type of permissions, programmatic access, and how they are used. To understand programmatic code access permission in more granular fashion, we created a Window Form and place some button controls which try to read or write a local text file. We first set up the permission that we want and grant the code up to the appropriate access level. Then we use the code that accesss our security object to illustrate the effect our permissions have on the code that accesses the object.

This example illustrates the use of the FileIOPermission class. The file c:/temp/xyz.txt has been secured at the operating system level so that no one can access it. The following program required these namespace to successfully execute this program.

using System.Security;
using System.Security.Principal;
using System.Security.Permissions;
using System.IO;

FileIOPermission ff = new FileIOPermission(FileIOPermissionAccess.Write,"c:/temp/xyz.txt");
     ff.Assert();

     try
     {
       StreamWriter objW= new   StreamWriter(File.Open("c:/temp/xyz.txt",FileMode.Open));
       objW.WriteLine("testing");
       objW.Flush();
       objW.Close();
       objW = null;
     }
     catch(Exception err)
     {
        MessageBox.Show(err.Message);
     }

Here we use the Assert() method, which declares that the resources should be accessible even if the caller has not been granted the permission to access the resource. So in this case, since the file is secured at the operating system level, we get the following error;


Figure 1.3

Now, let’s look another scenario where operating impose full rights to resource, but the code permissions sets to Deny as following:

CodeAccessPermission  perm = new FileIOPermission(FileIOPermissionAccess.AllAccess,"c:/temp/xyz.txt");
            perm.Deny();

            try
            {
                StreamReader objW= File.OpenText(@"c:/temp/xyz.txt");
                CodeAccessPermission.RevertDeny();
                objW = null;
            }
            catch(Exception err)
            {
                MessageBox.Show(err.Message);
            }

The Deny method denies all the callers access to the object, regardless of whether the operating system granted them permission. We catch the following error in our exception handler as shown:


Figure 1.4

Code Access Security Tools (caspol.exe)

.NET includes a command-line utility caspol.exe to configure, view the security policy of a particular assembly. Using caspol.exe you can specify what level of trust you have for each code access group as well as managing code groups and permissions in more granular fashion. This utility helps us to configure and view security policy at both Machine level and User level.

Note:In the .NET Framework version 3.5 and earlier versions, CAS policy is always in effect. In the .NET Framework 4, CAS policy must be enabled. It suggested making the following entry in the app.config or Machine.config file to suppress the warning message.

<configuration>
<runtime>
<LegacyCasPolicy enabled=”true”/>
</runtime>
</configuration>

To use caspol.exe just go to StartàProgramsàMS Visual Studio 2010àVisual Studio ToolsàCommand Prompt. Let’s take a glimpse over this utility as;


Figure 1.5

Want to learn more?? The InfoSec Institute Advanced Computer Forensics Training trains you on critical forensic skills that are difficult to master outside of a lab enviornment. Already know how to acquire forensically sound images? Perform file carving? Take your existing forensic knowledge further and sharpen your skills with this Advanced Computer Forensics Boot Camp from InfoSec Institute. Upon the completion of our Advanced Computer Forensics Boot Camp, students will know how to:
  • Perform Volume Shadow Copy (VSC) analysis
  • Advanced level file and data structure analysis for XP, Windows 7 and Server 2008/2012 systems
  • Timeline Analysis & Windows Application Analysis
  • iPhone Forensics

Policy

The Security Policy is the predefined set of rules that the CLR follows when determining the permissions to grant to code; .NET framework ships with four policy levels – User, Enterprise, and Machine. The three policy levels are discussed as followed:

  • User Policy

    This policy is administered by and for the current logged user, and evaluated at the time it is granted.

  • Enterprise

    This policy is applied when a particular application is being used on all the systems in the enterprise. This policy affects every user and system in the enterprise.

  • Machine

    This policy is administered by the system administrator or domain controller. The settings on this level affect only the applications that run on the local system.

When you run caspol.exe as an administrator account, it defaults to the machine level, but if you logged out and logged back as a user who is not an administrator user then caspol.exe will default to the User level instead. To work with code groups and permissions on the user or enterprise level using caspol.exe, add either the –enterprise or –user argument to change the command mode as following:


Figure 1.6

Here you notice a warning message which is occurring due to CAS policy disabled. You have to enable it in the project app.config file as discussed earlier. Now, run the same command, but this time with code groups at machine level as following:


Figure 1.2

Conclusion

In this article, you have learned how to implement the security initiatives at the source code level and you have also learned that, for an assembly to execute, it must have the relevant permissions at the machine, user and enterprise level as well as the correct role base permissions and the relevant Windows account. You also become familiar with the security tools caspol.exe to manage security permissions.