What are the exact security implications of setting ApplicationBase of a slave sandbox domain to the same path as the hosting domain?
I found MSDN guidelines that state that ApplicationBase should be different for the slave domain "If the ApplicationBase settings are the same, the partial-trust application can get the hosting application to load (as fully trusted) an exception it defines, thus exploiting it" (p. 3):
http://msdn.microsoft.com/en-us/library/bb763046.aspx
How exactly would this exploit work?
In my scenario I am willing to run all assemblies located under the ApplicationBase in full trust. I am sandboxing the slave AppDomain exclusively to limit the rights of dynamically generated assemblies within that domain. I tried following the guidelines but changing the ApplicationBase property seems to break a bi-directional communication bridge I have between the domains, due to an assembly loading into LoadFrom context, so I would like to avoid it.
Sample F# code demonstrating the problem with distinct ApplicationBase values:
module Main =
open System
open System.Diagnostics
open System.IO
open System.Reflection
open System.Security
open System.Security.Permissions
open System.Security.Policy
/// Change this switch to observe the problem.
let useSameApplicationBase = true
let getStrongName (a: Assembly) =
match a.Evidence.GetHostEvidence<StrongName>() with
| null -> None
| sn -> Some sn
let getAssemblies () =
[|
Assembly.GetExecutingAssembly()
|]
let buildAppDomain () =
let fullTrust =
getAssemblies ()
|> Array.choose getStrongName
let evidence = null
let appBase =
if useSameApplicationBase then
AppDomain.CurrentDomain.BaseDirectory
else
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Untrusted")
let setup = AppDomainSetup(ApplicationBase = appBase)
let perms = PermissionSet(PermissionState.None)
AppDomain.CreateDomain("SLAVE", null, setup, perms, fullTrust)
[<Sealed>]
type Backer() =
inherit MarshalByRefObject()
member this.Pong() =
Console.WriteLine("PONG IN DOMAIN = {0}", AppDomain.CurrentDomain.FriendlyName)
[<Sealed>]
type Sandbox() =
inherit MarshalByRefObject()
member this.Start(backer: obj) =
Console.WriteLine("RUN IN SLAVE DOMAIN = {0}", AppDomain.CurrentDomain.FriendlyName)
(backer :?> Backer).Pong()
let test () =
let dom = buildAppDomain ()
try
let handle =
Activator.CreateInstanceFrom(dom,
typeof<Sandbox>.Assembly.Location,
typeof<Sandbox>.FullName)
let sandbox = handle.Unwrap() :?> Sandbox
sandbox.Start(Backer())
finally
AppDomain.Unload(dom)
test ()