如果ApplicationBase是沙盒应用程序域有什么不同? [英] Should ApplicationBase be different for the sandbox AppDomain?

查看:106
本文介绍了如果ApplicationBase是沙盒应用程序域有什么不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是从沙箱域的设置ApplicationBase以相同的路径托管域的确切安全问题?

我发现MSDN准则指出ApplicationBase应该是从域名不同如果ApplicationBase设置是一样的,部分信任的应用程序可以让宿主应用程序加载(如完全可信),它定义了一个异常,从而利用它(第3页):

http://msdn.microsoft.com/en-us/library/ bb763046.aspx

究竟是如何将这个漏洞的工作?

在我的情况,我愿意在运行完全信任设下的ApplicationBase的所有组件。我是沙盒奴隶的AppDomain专门限制域内动态生成组件的权利。我想下面的指导方针,但改变ApplicationBase属性似乎打破一个双向沟通的桥梁我有域之间,由于一个组件加载到LoadFrom上下文,所以我想,以避免它。

样品F#code展示具有鲜明的ApplicationBase值的问题:

 模块主要=

    开放系统
    开System.Diagnostics程序
    开System.IO
    开放的System.Reflection
    开System.Security程序
    开System.Security.Permissions
    开System.Security.Policy

    ///更改此开关来观察这个问题。
    让useSameApplicationBase =真

    让getStrongName(一:大会)=
        匹配a.Evidence.GetHostEvidence<强名称>()与
        |空 - >无
        | SN  - >一些SN

    让getAssemblies()=
        [|
            Assembly.GetExecutingAssembly()
        |]

    让buildAppDomain()=
        让FullTrust的=
            getAssemblies()
            |> Array.choose getStrongName
        让证据= NULL
        让我们的appBase =
            如果useSameApplicationBase然后
                AppDomain.CurrentDomain.BaseDirectory
            其他
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory,不信任)
        让设置= AppDomainSetup(ApplicationBase =的appBase)
        让烫发=的PermissionSet(PermissionState.None)
        AppDomain.CreateDomain(从,空,设置,烫发,FullTrust的)

    [<密封>]
    键入靠山()=
        继承MarshalByRefObject的()
        会员this.Pong()=
            Console.WriteLine(傍域= {0},AppDomain.CurrentDomain.FriendlyName)

    [<密封>]
    键入沙盒()=
        继承MarshalByRefObject的()
        会员this.Start(支持者:OBJ)=
            Console.WriteLine(运行从属域= {0},AppDomain.CurrentDomain.FriendlyName)
            (靠山:>靠山).Pong()

    让试验(+)=
        让DOM = buildAppDomain()
        尝试
            让手柄=
                Activator.CreateInstanceFrom(DOM,
                    typeof运算<沙盒> .Assembly.Location,
                    typeof运算<沙盒> .FullName)
            让沙盒= handle.Unwrap():>?砂箱
            sandbox.Start(巴克())
        最后
            AppDomain.Unload(DOM)

    测试 ()
 

解决方案

 模块主要=

    开放系统
    开System.Diagnostics程序
    开System.IO
    开放的System.Reflection
    开System.Security程序
    开System.Security.Permissions
    开System.Security.Policy

    ///更改此开关来观察这个问题。
    让useSameApplicationBase = FALSE

    让getStrongName(一:大会)=
        匹配a.Evidence.GetHostEvidence<强名称>()与
        |空 - >无
        | SN  - >一些SN

    让getAssemblies()=
        [|
            Assembly.GetExecutingAssembly()
        |]

    让buildAppDomain()=
        让FullTrust的=
            getAssemblies()
            |> Array.choose getStrongName
        让证据= NULL
        让我们的appBase =
            如果useSameApplicationBase然后
                AppDomain.CurrentDomain.BaseDirectory
            其他
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory,不信任)
        让设置= AppDomainSetup(ApplicationBase =的appBase)
        让烫发=的PermissionSet(PermissionState.None)
        AppDomain.CreateDomain(从,空,设置,烫发,FullTrust的)

    模块AssemblyResolveSetup =
        让安装()=
            让resolveHandler =
                    ResolveEventHandler(
                        有趣_ ARGS  - >
                            //试图找到所需的组件,当前域
                            让名=的AssemblyName(args.Name)
                            让asmOpt =
                                AppDomain.CurrentDomain.GetAssemblies()
                                |> Array.tryFind(ASM乐趣 - > AssemblyName.ReferenceMatchesDefinition(的AssemblyName(asm.FullName),名称))
                            defaultArg asmOpt空
                    )
            AppDomain.CurrentDomain.add_AssemblyResolve(resolveHandler)

    [<密封>]
    键入靠山()=
        继承MarshalByRefObject的()
        会员this.Pong()=
            Console.WriteLine(傍域= {0},AppDomain.CurrentDomain.FriendlyName)

    [<密封>]
    键入沙盒()=
        继承MarshalByRefObject的()
        做AssemblyResolveSetup.install()
        会员this.Start(支持者:OBJ)=
            Console.WriteLine(运行从属域= {0},AppDomain.CurrentDomain.FriendlyName)
            (靠山:>靠山).Pong()

    让试验(+)=
        让DOM = buildAppDomain()
        尝试
            让手柄=
                Activator.CreateInstanceFrom(DOM,
                    typeof运算<沙盒> .Assembly.Location,
                    typeof运算<沙盒> .FullName)
            让沙盒= handle.Unwrap():>?砂箱
            sandbox.Start(巴克())
        最后
            AppDomain.Unload(DOM)

    测试 ()
 

更新(假设测试code包含在装配Sandbox.exe)

问::如何解决通过查看SLAVE(CurrentDomain)发现在SLAVE装配,听起来像是一个恶性循环。

SLAVE域已经包含Sandbox.exe但它加载LoadFrom上下文,所以它不会自动解决依赖于负载情况下(选择一个绑定上下文)。

问::不是的AssemblyName(asm.FullName)为什么它打破了asm.GetName()

Assembly.GetName需要的FileIOPermission,Assembly.FullName - 不要让我觉得,如果你更换

 的AssemblyName(asm.FullName)
 

 让名=的AssemblyName(args.Name)
设p =新的FileIOPermission(PermissionState.Unrestricted)
p.Assert()
尝试
    让asmOpt =
        AppDomain.CurrentDomain.GetAssemblies()
        |> Array.tryFind(ASM乐趣 - > AssemblyName.ReferenceMatchesDefinition(asm.GetName(),名称))
    defaultArg asmOpt空
最后
    codeAccessPermission.RevertAssert()
 

这也应该工作(没试过)

问::为什么制动器静做AssemblyResolveSetup.install()

这是唯一的F#的特定位置的问题。我猜你的测试项目是编译到exe单个文件的项目。每F#规格:

对于有一个隐含的切入点,静态初始化为上出现的最后一个文件的可执行文件 命令行是隐入口点函数的主体。

所以,code。在静做'块将被放置'()测试中隐含的切入点,而不是被编译成静态构造函数体调用之前。修复 - 要么把测试模块的独立非最后一个文件或将其移动到库

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 ()

解决方案

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 = false

    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)

    module AssemblyResolveSetup = 
        let install() = 
            let resolveHandler = 
                    ResolveEventHandler(
                        fun _ args ->
                            // try to find requested assembly in current domain
                            let name = AssemblyName(args.Name)
                            let asmOpt =
                                AppDomain.CurrentDomain.GetAssemblies()
                                |> Array.tryFind(fun asm -> AssemblyName.ReferenceMatchesDefinition(AssemblyName(asm.FullName), name))
                            defaultArg asmOpt null
                    )        
            AppDomain.CurrentDomain.add_AssemblyResolve(resolveHandler)

    [<Sealed>]
    type Backer() =
        inherit MarshalByRefObject()
        member this.Pong() =
            Console.WriteLine("PONG IN DOMAIN = {0}", AppDomain.CurrentDomain.FriendlyName)

    [<Sealed>]
    type Sandbox() =
        inherit MarshalByRefObject()
        do AssemblyResolveSetup.install()
        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 ()

UPDATE (Assuming that test code is contained in assembly Sandbox.exe)

Q:how resolution finds the assembly in SLAVE by looking in SLAVE (CurrentDomain), sounds like a vicious circle

SLAVE domain already contains Sandbox.exe but it is loaded in LoadFrom context so it won't be probed automatically when resolving dependencies for Load context (Choosing a binding context).

Q: why it breaks for asm.GetName() instead of AssemblyName(asm.FullName)

Assembly.GetName requires FileIOPermission, Assembly.FullName - don't so I think if you replace

AssemblyName(asm.FullName)

with

let name = AssemblyName(args.Name)
let p = new FileIOPermission(PermissionState.Unrestricted)
p.Assert()
try
    let asmOpt =
        AppDomain.CurrentDomain.GetAssemblies()
        |> Array.tryFind(fun asm -> AssemblyName.ReferenceMatchesDefinition(asm.GetName(), name))
    defaultArg asmOpt null
finally
    CodeAccessPermission.RevertAssert()

this should also work (haven't tried)

Q: why it brakes for static do AssemblyResolveSetup.install()

this is the only F# specific issue here. I guess your test project is single file project that is compiled to exe. Per F# spec:

For executable files that have an implicit entry point, the static initializer for the last file that appears on the command line is the body of the implicit entry point function.

So code in 'static do' block will be placed before the call to 'test()' in the implicit entry point instead of being compiled to the body of static constructor. Fix - either put Test module to the separate non-last file or move it to the library

这篇关于如果ApplicationBase是沙盒应用程序域有什么不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆