|
security
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Sandboxing AppDomainso that I can restrict it's permissions. I based my AppDomain setup off some blog entries here: http://blogs.msdn.com/shawnfa/archive/2004/11/02/251239.aspx http://blogs.msdn.com/shawnfa/archive/2004/11/08/253971.aspx The code to create the AppDomain is below. I'm mimicing the internet zone permission set in my test application for now. I would like to use a custom permission set so that I have fine-grained control over the sandbox security. If I call a method on the plugin implementation which displays a message box, I get the following error: System.Security.Policy.PolicyException: Required permissions cannot be acquired. If change the implementation below to instead initialize and use a NamedPermissionSet with the "Internet" zone specified in the constructor, the plugin works as expected. I do not understand why the same permissions being created manually fails vs. the named permission set. Any help is appreciated. Thanks, Kris public AppDomain CreateAppDomain() { PolicyStatement emptyPolicy = new PolicyStatement(new PermissionSet(PermissionState.None)); UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), emptyPolicy); // now grant permissions explicitly for the sandbox PermissionSet permissionSet = new PermissionSet(PermissionState.None); permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); permissionSet.AddPermission(new UIPermission(UIPermissionWindow.SafeTopLevelWindows, UIPermissionClipboard.OwnClipboard)); permissionSet.AddPermission(new PrintingPermission(PrintingPermissionLevel.SafePrinting)); permissionSet.AddPermission(new FileDialogPermission(FileDialogPermissionAccess.Open)); PolicyStatement permissions = new PolicyStatement(permissionSet); policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), permissions)); // create a policy level for the policy tree PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel(); appDomainLevel.RootCodeGroup = policyRoot; // create the AppDomain which lives under this policy AppDomain result = AppDomain.CreateDomain("Plugin-Sandbox"); result.SetAppDomainPolicy(appDomainLevel); return result; } Unfortunately, I can't seem to reproduce the problem. Might you be able to
provide sample code for both the target method and its invocation? <krsg***@gmail.com> wrote in message Show quoteHide quote news:1124312040.984766.142870@g44g2000cwa.googlegroups.com... >I am trying to load an untrusted assembly within a separate AppDomain > so that I can restrict it's permissions. I based my AppDomain setup > off some blog entries here: > > http://blogs.msdn.com/shawnfa/archive/2004/11/02/251239.aspx > http://blogs.msdn.com/shawnfa/archive/2004/11/08/253971.aspx > > The code to create the AppDomain is below. I'm mimicing the internet > zone permission set in my test application for now. I would like to > use a custom permission set so that I have fine-grained control over > the sandbox security. If I call a method on the plugin implementation > which displays a message box, I get the following error: > > System.Security.Policy.PolicyException: Required permissions cannot be > acquired. > > If change the implementation below to instead initialize and use a > NamedPermissionSet with the "Internet" zone specified in the > constructor, the plugin works as expected. I do not understand why the > same permissions being created manually fails vs. the named permission > set. > > Any help is appreciated. > > Thanks, > > Kris > > > public AppDomain CreateAppDomain() > { > PolicyStatement emptyPolicy = new PolicyStatement(new > PermissionSet(PermissionState.None)); > UnionCodeGroup policyRoot = new UnionCodeGroup(new > AllMembershipCondition(), emptyPolicy); > > // now grant permissions explicitly for the sandbox > PermissionSet permissionSet = new > PermissionSet(PermissionState.None); > permissionSet.AddPermission(new > SecurityPermission(SecurityPermissionFlag.Execution)); > permissionSet.AddPermission(new > UIPermission(UIPermissionWindow.SafeTopLevelWindows, > UIPermissionClipboard.OwnClipboard)); > permissionSet.AddPermission(new > PrintingPermission(PrintingPermissionLevel.SafePrinting)); > permissionSet.AddPermission(new > FileDialogPermission(FileDialogPermissionAccess.Open)); > > PolicyStatement permissions = new PolicyStatement(permissionSet); > policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), > permissions)); > > // create a policy level for the policy tree > PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel(); > appDomainLevel.RootCodeGroup = policyRoot; > > // create the AppDomain which lives under this policy > AppDomain result = AppDomain.CreateDomain("Plugin-Sandbox"); > result.SetAppDomainPolicy(appDomainLevel); > return result; > } > Hi Nicole, here is a more comprehensive code sample:
First I have an IPlugin interface in a shared assemblyy with two simple methods. public interface IPlugin { void DoSomething(); void DoSomethingBad(); } In my concrete plugin assembly is the corresponding implementation: public class PluginImpl : MarshalByRefObject, IPlugin { public void DoSomething() { // this should be fine since its a msgbox MessageBox.Show("Hello from plugin: " + AppDomain.CurrentDomain.FriendlyName); } public void DoSomethingBad() { // this should not be allowed SaveFileDialog dialog = new SaveFileDialog(); dialog.ShowDialog(); } } In my plugin host EXE I create the sandboxed AppDomain instance and load the plugin into it: class PluginHost { [STAThread] static void Main(string[] args) { try { AppDomain pluginDomain = CreateAppDomain(); IPlugin plugin = (IPlugin)pluginDomain.CreateInstanceAndUnwrap( "Spike.AppDomainHosting.Plugin", "Spike.AppDomainHosting.Plugin.PluginImpl"); // interact with the plugin plugin.DoSomething(); // now tear down the appdomain AppDomain.Unload(pluginDomain); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } private static AppDomain CreateAppDomain() { // default all code to no permissions PolicyStatement emptyPolicy = new PolicyStatement(new PermissionSet(PermissionState.None)); UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), emptyPolicy); // now grant permissions explicitly for the sandbox PermissionSet permissionSet = new PermissionSet(PermissionState.None); permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); permissionSet.AddPermission(new UIPermission(UIPermissionWindow.SafeTopLevelWindows, UIPermissionClipboard.OwnClipboard)); permissionSet.AddPermission(new PrintingPermission(PrintingPermissionLevel.SafePrinting)); permissionSet.AddPermission(new FileDialogPermission(FileDialogPermissionAccess.Open)); PolicyStatement permissions = new PolicyStatement(permissionSet); policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), permissions)); // create a policy level for the policy tree PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel(); appDomainLevel.RootCodeGroup = policyRoot; // create the AppDomain which lives under this policy AppDomain result = AppDomain.CreateDomain("Plugin-Sandbox"); result.SetAppDomainPolicy(appDomainLevel); return result; } } } When I call the PluginImpl.DoSomething() method which displays a message box (and should be allowed based on the permissions I'm assigning in PluginHost.CreateAppDomain method), I'm met with the following exception: System.Security.Policy.PolicyException: Required permissions cannot be acquired. Server stack trace: at Spike.AppDomainHosting.Plugin.PluginImpl.DoSomething() at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(MethodBase mb, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Spike.AppDomainHosting.Shared.IPlugin.DoSomething() at Spike.AppDomainHosting.PluginHost.Main(String[] args) in e:\dev\spike\spike.appdomainhosting\pluginhost.cs:line 33 If within CreateAppDomain, I substitute my created PermissionSet for a NamedPermissionSet with the "Internet" name specified, the code works (sort of.) As I was writing this I just realized that even under the NamedPermissionSet, the code is able to instantiate the SaveFileDialog, which should be prohibited under the Internet level of trust. :-( Any help on sorting this out is really appreciated! Thanks, Kris "kris" <krsg***@gmail.com> wrote in message <snip>news:1124563307.946760.32560@g43g2000cwa.googlegroups.com... > Hi Nicole, here is a more comprehensive code sample: Thanks, that really helped me with figuring out what you were doing. > If within CreateAppDomain, I substitute my created PermissionSet for a That's because creating a permission set from a name doesn't actually > NamedPermissionSet with the "Internet" name specified, the code works > (sort of.) As I was writing this I just realized that even under the > NamedPermissionSet, the code is able to instantiate the SaveFileDialog, > which should be prohibited under the Internet level of trust. :-( populate the new permission set with the policy-set permissions for the named permission set. Instead, something like "new NamedPermissionSet("any name")" generates an _unrestricted_ permission set (same as FullTrust). > Any help on sorting this out is really appreciated! Your underlying problem is that the target assembly doesn't have sufficient permissions to deal with the remoting plumbing. You might want to re-read the parts of Shawn's blog postings that deal with the use of MarshalByRefObject. Here are some pointers: 1. The MarshalByRefObject subtype that will be the remoting invocation target should be in a fully trusted assembly that you will create (not the in the plug-in implementation assembly). 2. You should call the plug-in implementation from a copy of the assembly described in #1 that has been loaded into the restricted app domain. 3. The policy for the restricted app domain should restrict the permissions of all assemblies other than the "conductor" assembly described in #1. 4. Since the plug-in implementations will not be remoting targets (at least with respect to the permissions restriction mechanism), there's no need for them to subclass MarshalByRefObject. Does that make a bit more sense? Hi Nicole, this makes more sense (especially my confusion on the named
permission set), thanks for the response. I've made some changes based on your comments as well as rereading the MarshalByRefObject blog entry here: http://blogs.msdn.com/shawnfa/archive/2004/11/02/251239.aspx I'm still encountering the PolicyException stating that required permissions cannot be acquired. Here's the steps I've taken: -The concrete plugin implementation no longer derives from MBR, it only implements the interface from the shared assembly. - In the shared assembly, I now have a PluginFactory implementation that derives from MBR, and loads a concrete plugin implementation given an assembly path and type name. Instead of returning the plugin instance, which would mean loading of the concrete plugin type in the host AppDomain, it wraps the IPlugin implementation in a PluginProxy object, which derives from MBR. This forwards all calls to the concrete plugin and all within the context of the restricted AppDomain. This is the now the conductor as you described it. - I signed both the plugin host and shared assemblies. In the AppDomain setup code based on the blog posts, I assign a StrongNameMembershipCondition for the shared assembly and grant it full permissions. This too is based on the post here: http://blogs.msdn.com/shawnfa/archive/2004/10/26/248114.aspx When attempting to call IPlugin.DoSomething() which displays a MessageBox (allowable under the internet named permission) I am failing with the security exception: System.Security.Policy.PolicyException: Required permissions cannot be acquired. The AppDomain setup/initializiation is verbatim from the blog posts cited, and this revised remoting model seems to match your comments as well as the blog entries. Since the plugin is now only a reference within a "safe" MBR which I own in my shared/conductor assembly, the remoting stack would seem to be out of the picture. I'm still unclear as to why this still fails. Thanks again! Kris Might you be able to provide a relevant code sample similar to the one from
your last message? Looking at what your code is actually doing would be far more efficient than attempting to repro by guessing at some of the pickier details... <g> Show quoteHide quote "kris" <krsg***@gmail.com> wrote in message news:1124778934.019889.32750@z14g2000cwz.googlegroups.com... > Hi Nicole, this makes more sense (especially my confusion on the named > permission set), thanks for the response. I've made some changes based > on your comments as well as rereading the MarshalByRefObject blog entry > here: > > http://blogs.msdn.com/shawnfa/archive/2004/11/02/251239.aspx > > I'm still encountering the PolicyException stating that required > permissions cannot be acquired. Here's the steps I've taken: > > -The concrete plugin implementation no longer derives from MBR, it only > implements the interface from the shared assembly. > > - In the shared assembly, I now have a PluginFactory implementation > that derives from MBR, and loads a concrete plugin implementation given > an assembly path and type name. Instead of returning the plugin > instance, which would mean loading of the concrete plugin type in the > host AppDomain, it wraps the IPlugin implementation in a PluginProxy > object, which derives from MBR. This forwards all calls to the > concrete plugin and all within the context of the restricted AppDomain. > This is the now the conductor as you described it. > > - I signed both the plugin host and shared assemblies. In the > AppDomain setup code based on the blog posts, I assign a > StrongNameMembershipCondition for the shared assembly and grant it full > permissions. This too is based on the post here: > > http://blogs.msdn.com/shawnfa/archive/2004/10/26/248114.aspx > > When attempting to call IPlugin.DoSomething() which displays a > MessageBox (allowable under the internet named permission) I am failing > with the security exception: > > System.Security.Policy.PolicyException: Required permissions cannot be > acquired. > > The AppDomain setup/initializiation is verbatim from the blog posts > cited, and this revised remoting model seems to match your comments as > well as the blog entries. Since the plugin is now only a reference > within a "safe" MBR which I own in my shared/conductor assembly, the > remoting stack would seem to be out of the picture. I'm still unclear > as to why this still fails. > > Thanks again! > > Kris > Hi Nicole, to give you full context as to my approach, I've emailed you
my current sample directly to your email. If and when the issue is identified, I'll post back the issue/solution to the list for the record. If anyone else is interested in the sample in the interim please let me know and I'll forward it. Thanks again, Kris. You might have better luck if you were to grant full trust to .NET Framework
assemblies. <g> The easiest way to fix this would probably be to add a new code group that uses a StrongNameMembershipCondition based on only the key (but not name or version) from mscorlib (typeof(object).Assembly). HTH, Nicole Show quoteHide quote "kris" <krsg***@gmail.com> wrote in message news:1124805268.814622.63760@z14g2000cwz.googlegroups.com... > Hi Nicole, to give you full context as to my approach, I've emailed you > my current sample directly to your email. If and when the issue is > identified, I'll post back the issue/solution to the list for the > record. If anyone else is interested in the sample in the interim > please let me know and I'll forward it. > > Thanks again, Kris. > Hi Nicole, I wish you could of heard the slap to my forehead! :)
Thanks again for your help. By adding full-trust, strong name membership code groups for mscorlib and System.Windows.Forms things worked wonderfully. I'm a little unclear as to why mscorlib and the winforms stuff have different public keys but that's a secondary issue. Nix that last message, I had misunderstood your last comment regarding
the StrongNameMembershipCondition which explains the issue I had mentioned. Thanks again. Nix my last too. <g> I answered before seeing yours...
Show quoteHide quote "kris" <krsg***@gmail.com> wrote in message news:1124822247.338042.8290@g14g2000cwa.googlegroups.com... > Nix that last message, I had misunderstood your last comment regarding > the StrongNameMembershipCondition which explains the issue I had > mentioned. Thanks again. > I can't seem to shake the dreaded security exception, this time however
in a different context. The final goal of my plugin proof of concept is to allow the plugin host to provide services to the plugin. My plugin host implements IApplication which is handed to the IPlugin instance to allow callbacks to the host. It would appear that remoting is again the culprit given that my plugin is interacting with a MarshalByRefObject from within the restricted domain. I attempted to wrap the MBR with a proxy which is handed to plugin, and created within the fully-trusted shared/conductor assembly. This would then forward calls from the plugin off to the actual MBR. Unfortunately, I was met with the same error. The exception states that: System.Security.SecurityException: Security error. at Spike.AppDomainHosting.Plugin.PluginImpl.Handshake(IApplication application) at Spike.AppDomainHosting.Shared.PluginProxy.Handshake(IApplication application) in c:\dev\spike\plugins\spike.appdomainhosting.shared\pluginproxy.cs:line 43 The granted set of the failing assembly was: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Access="Open"/> <IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Allowed="DomainIsolationByUser" UserQuota="10240"/> <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Execution"/> <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Window="SafeTopLevelWindows" Clipboard="OwnClipboard"/> <IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Level="SafePrinting"/> <IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Url="file://C:/dev/spike/plugins/Spike.AppDomainHosting.Plugin/bin/Debug/Spike.AppDomainHosting.Plugin.dll"/> <IPermission class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Zone="MyComputer"/> </PermissionSet> Thanks again, Kris Hmm... Without attempting a repro, it's hard to be sure, but I suspect that
this particular exception might simply be the result of attempting to call into a strongly named assembly (either the proxy or the host) from a partially trusted assembly (the plugin implementation). See http://blogs.msdn.com/shawnfa/archive/2005/02/04/367390.aspx for an explanation of why this exception is thrown and how to address the problem. Show quoteHide quote "kris" <krsg***@gmail.com> wrote in message news:1124913917.327893.29230@f14g2000cwb.googlegroups.com... >I can't seem to shake the dreaded security exception, this time however > in a different context. The final goal of my plugin proof of concept > is to allow the plugin host to provide services to the plugin. My > plugin host implements IApplication which is handed to the IPlugin > instance to allow callbacks to the host. > > It would appear that remoting is again the culprit given that my plugin > is interacting with a MarshalByRefObject from within the restricted > domain. I attempted to wrap the MBR with a proxy which is handed to > plugin, and created within the fully-trusted shared/conductor assembly. > This would then forward calls from the plugin off to the actual MBR. > Unfortunately, I was met with the same error. The exception states > that: > > System.Security.SecurityException: Security error. > at Spike.AppDomainHosting.Plugin.PluginImpl.Handshake(IApplication > application) > at Spike.AppDomainHosting.Shared.PluginProxy.Handshake(IApplication > application) in > c:\dev\spike\plugins\spike.appdomainhosting.shared\pluginproxy.cs:line > 43 > > The granted set of the failing assembly was: > <PermissionSet class="System.Security.PermissionSet" > version="1"> > <IPermission > class="System.Security.Permissions.FileDialogPermission, mscorlib, > Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > version="1" > Access="Open"/> > <IPermission > class="System.Security.Permissions.IsolatedStorageFilePermission, > mscorlib, Version=1.0.5000.0, Culture=neutral, > PublicKeyToken=b77a5c561934e089" > version="1" > Allowed="DomainIsolationByUser" > UserQuota="10240"/> > <IPermission class="System.Security.Permissions.SecurityPermission, > mscorlib, Version=1.0.5000.0, Culture=neutral, > PublicKeyToken=b77a5c561934e089" > version="1" > Flags="Execution"/> > <IPermission class="System.Security.Permissions.UIPermission, > mscorlib, Version=1.0.5000.0, Culture=neutral, > PublicKeyToken=b77a5c561934e089" > version="1" > Window="SafeTopLevelWindows" > Clipboard="OwnClipboard"/> > <IPermission class="System.Drawing.Printing.PrintingPermission, > System.Drawing, Version=1.0.5000.0, Culture=neutral, > PublicKeyToken=b03f5f7f11d50a3a" > version="1" > Level="SafePrinting"/> > <IPermission > class="System.Security.Permissions.UrlIdentityPermission, mscorlib, > Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > version="1" > > Url="file://C:/dev/spike/plugins/Spike.AppDomainHosting.Plugin/bin/Debug/Spike.AppDomainHosting.Plugin.dll"/> > <IPermission > class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, > Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > version="1" > Zone="MyComputer"/> > </PermissionSet> > > Thanks again, > > Kris > "kris" <krsg***@gmail.com> wrote in message They don't. Both mscorlib.dll and System.Windows.Forms.dll are signed with news:1124819988.463476.47470@g44g2000cwa.googlegroups.com... > Hi Nicole, I wish you could of heard the slap to my forehead! :) > Thanks again for your help. By adding full-trust, strong name > membership code groups for mscorlib and System.Windows.Forms things > worked wonderfully. I'm a little unclear as to why mscorlib and the > winforms stuff have different public keys but that's a secondary issue. the same key, which is generally referred to as the "ECMA key". There's another key that's used for signing some of the other assemblies that ship with the .NET Framework (e.g.: System.Drawing.dll, System.Web.dll). If you look under the All_Code\My_Computer_Zone node of the default machine-level CAS policy, you'll see two code groups that grant full trust to assemblies signed with each of these keys. If you found that you needed to add full trust code groups for both mscorlib.dll and System.Windows.Forms.dll to your app domain policy, that's probably because your CreateStrongNameMembershipCondition method created a membership condition based on key, name, and version as opposed to just on the key. If you want to exclude the name and version from the membership condition, supply null values for the corresponding constructor parameters.
can you put a strong name assembly in a role?
Can't determine if a file exists MD5 or SHA1 or ??? IIS Delegation 'System.Security.SecurityException' when running .exe file from ot windows forms UserControl compiled with beta 2 doesn't work with IE Strong Name broken? CAS Permission Sets CryptGenKey & CryptImportKey slow in certain situations asp.net err |
|||||||||||||||||||||||