gpt4 book ai didi

.net - 沙盒 AppDomain 的 ApplicationBase 是否应该不同?

转载 作者:行者123 更新时间:2023-12-04 05:25:08 26 4
gpt4 key购买 nike

将从属沙箱域的 ApplicationBase 设置为与托管域相同的路径的确切安全含义是什么?

我发现 MSDN 指南指出,从域的 ApplicationBase 应该不同“如果 ApplicationBase 设置相同,则部分信任应用程序可以让托管应用程序加载(完全信任)它定义的异常,从而利用它” (第 3 页):

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

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

在我的场景中,我愿意以完全信任的方式运行位于 ApplicationBase 下的所有程序集。我专门对从属 AppDomain 进行沙盒处理,以限制该域内动态生成的程序集的权限。我尝试遵循指南,但由于程序集加载到 LoadFrom 上下文中,更改 ApplicationBase 属性似乎破坏了我在域之间拥有的双向通信桥梁,所以我想避免它。

示例 F# 代码演示了具有不同 ApplicationBase 值的问题:

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

更新(假设测试代码包含在程序集 Sandbox.exe 中)

:分辨率如何通过查看 SLAVE (CurrentDomain) 找到 SLAVE 中的程序集,听起来像是一个恶性循环

SLAVE 域已经包含 Sandbox.exe,但它是在 LoadFrom 上下文中加载的,因此在解析 Load 上下文 ( Choosing a binding context ) 的依赖项时不会自动探测它。

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

Assembly.GetName 需要 FileIOPermission、Assembly.FullName - 如果您更换,请不要这样
AssemblyName(asm.FullName)


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

这也应该有效(没试过)

:为什么它会因为静态而刹车?AssemblyResolveSetup.install()

这是这里唯一的 F# 特定问题。我猜您的测试项目是编译为 exe 的单文件项目。根据 F# 规范:

对于具有隐式入口点的可执行文件,出现在
命令行是隐式入口点函数的主体。

所以'static do' block 中的代码将被放置在隐式入口点中对'test()'的调用之前,而不是编译到静态构造函数的主体中。修复 - 将测试模块放入单独的非最后文件或将其移至库

关于.net - 沙盒 AppDomain 的 ApplicationBase 是否应该不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13280251/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com