Application Domains in the .NET framework
Application domains enable calling of external assemblies with optimal efficiency and security.
Services are assemblies that run in background, presenting no UI and controlled by specialised tools.
Lesson 1: Creating Application Domains
Application Domain = logical container allowing multiple assemblies to reside in one process, but prevents them from accessing each others memory. Offer many of the features of a process such as separate memory spaces and access to resources. More efficient than separate processes as there is not the overhead of launching separate processes.
.NET manages application domains, OS manages processes.
IIS ASP.NET worker process = example of application domain. If 10 people visit site simultaneously then 10 separate application domains are created (one for each user) within Aspnet_wp.exe to run 10 separate instances of the assembly.
Each instance of the assembly can store property called userName without concern that other instances will be able to access or overwrite the contents of the property. Same effect could be achieved by launching 10 separate processes, but this would be expensive in terms of start up and switching times.
Usually rely on run-time hosts (e.g. ASP.NET, Internet Explorer, the OS) to create application domains for assemblies. Use friendly tools such as IIS Manager and .NET Framework Configuration tool to control them.
Can create own application domains to isolate multiples instances of an assembly. Besides providing enhanced security also offers:
- Reliability isolate tasks that may cause process to terminate. If state of application domain becomes unstable it can be unloaded without affecting the rest of the process. Use when process must run for long periods of time without restarting.
- Efficiency If assembly loaded into default application domain it cannot be unloaded from memory whilst the process is running. If a second application domain is used then the assembly can be unloaded when not required. Use this technique to minimise the working set of long running processes that occasionally use large DLLs.
AppDomain Class
To use an application domain create instance of AppDomain class using one of the overloaded CreateDomain methods, e.g.
AppDomain d = AppDomain.Create("NewDomain");
Then call ExecuteAssembly to launch the assembly,
d.ExecuteAssembly("Assembly.exe");
To unload call the static Unload method.
AppDomain.Unload(d);
Lesson 2: Configuring Application Domains
Restricting permissions of application domain greatly reduces risk that assembly will cause malicious action, e.g. Purchase 3
rd party application to communicate with database. Attacker discovers vulnerability in this assembly and uses it to configure a spyware application to start automatically. To the user the security vulnerability appears to be your applications fault.
The same scenario with limited privileges: the attacker discovers the vulnerability in the 3
rd party assembly. When the attacker exploits the vulnerability to write files to the local hard drive, the file I/O is rejected because of insufficient privileges. While the vulnerability still exists, the limited privileges granted to the application domain prevented it from being exploited.
Above is an example of "defence-in-depth" - principal of providing multiple levels of protection so that still protected in event of vulnerability.
Providing Host Evidence For Assembly
When creating application domain and launching assemblies you have complete control over evidence. Evidence = information that runtime gather about assembly to determine what code groups it belongs to. These determine its privileges. Common forms of evidence = folder or website assembly is running from and digital signatures.
To provide evidence for assembly create a System.Security.Policy.Evidence object. Pass this as parameter to the overloaded ExecuteAssembly method. The constructor requires two object arrays one represents the host evidence, the other the assembly. Either can be null, usually only assign to the host evidence array.
Simplest way to control permissions assigned to assembly in an application domain is to pass Zone evidence, e.g.
object[] hostEvidence = {new Zone(SecurityZone.Internet)};
Evidence internetEvidence = new Evidence(hostEvidence, null);
AppDomain myDomain = AppDomain.CreateDomain("MyDomain");
myDomain.ExecuteAssembly("SecondAssembly.exe", internetEvidence);
Will result in application domain with the permission set granted to the Internet_Zone group (extremely restrictive).
Providing Host Evidence For Application Domain
Similar to providing evidence for new assembly. Uses overloaded AppDomain.CreateDomain
...
object[] hostEvidence = {new Zone(SecurityZone.Internet)};
Evidence appDomainEvidence = new Evidence(hostEvidence, null);
AppDomain myDomain = AppDomain.CreateDomain("MyDomain", appDomainEvidence);
myDomain.ExecuteAssembly("SecondAssembly.exe");
Configuring Application Domain Properties
Can use AppDomainSetup class to configure way the CLR creates application domains. Most important property is ApplicationBase that controls the root directory of the application. Other arguments used to configure a particular application domain. Changing properties of AppDomainSetup does not affect existing AppDomains, only new ones created by AppDomain.CreateDomain. To apply properties to application domain, create and configure AppDomainSetup object and pass to AppDomain.CreateDomain method, e.g.
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = "file://" + System.Environment.CurrentDirectory;
ads.DisallowCodeDownload = true;
AppDomain d = AppDomain.CreateDomain("New Domain", null, ads);
Lesson 3: Creating Windows Services
What is a service?
Processes that run in background without UI and in their own session. Can be automatically started when computer starts (even without user logging on). Ideal for applications that should execute constantly and do not require user interaction. Differences to other project types:
- Must be installed before it can function in meaningful way. Cannot debug directly, instead must install, start service and then attach debugger.
- Must create installation components for service applications. These install and register the service and create an entry for it in the Services Control Manager.
- Main method of service issues Run command for the services the project contains. The Run method loads the services into the Service Control Manager this code is written automatically by the Windows Services project template.
- Run in a different windows station than the interactive station of the logged on user. A windows station = secure object containing clipboard, global atoms and desktop items. Because the station is not interactive any dialogue boxes, etc. raised by the application will not be seen.
- Run in own security context and are started before user logs on to the computer on which they are installed. Choose carefully what account they run under, a service running under the system account has more permissions and privileges than a user account. The more privileges a service has, the more damage attackers can do if they exploit a security vulnerability.
Implementing Service
After creating services project:
- In designer properties modify ServiceBase.ServiceName property. Every service must have unique name very important to change this setting. This is not the friendly name seen in service snap-in, instead it is used by OS to identify service and for use by command line tools.
- Add code to OnStart to set-up polling / monitoring the service requires. OnStart does not perform the monitoring. It must return to the OS once the service has started. It must not loop or block.
- Add code to OnStop to perform the action required to stop the service.
- Optionally override OnPause, OnContinue and OnShutdown.