[IronPython] Safe execution of python scripts on my .net application

Nicolás Buttarelli nbuttarelli at gmail.com
Tue Dec 1 10:48:48 PST 2009


Hi all, I'm bringing again some problem that I though that it was solved for
me.

I have to run some python code that comes from a web service, so I want to
execute it in a sandbox with restricted permissions. I also want to execute
some .NET code from these scripts and I want to have all the permissions
(create files, access to the database, etc) for them. I have tried several
options and I can't get it working. I have follow the last options that Dino
told me but they didn't work either. I will try to explain all the options
that I have managed, please let me know if something is not clear enough.

*[1]* I am creating my AppDomain in the following way.

AppDomainSetup anAppDomainSetup = new AppDomainSetup();
anAppDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
anAppDomainSetup.ApplicationName = "Testing";
Evidence evidence = new Evidence();
evidence.AddHost(new Zone(SecurityZone.Internet));
return AppDomain.CreateDomain("Test Domain", evidence, anAppDomainSetup);

*[2]* Another option is to create it using *AppDomain.CreateDomain(aName,
aEvidence, anAppDomainSetup, aPermissionSet, aStrongNameArray)*, but I have
already told here, when you try to create the engine using *
Python.CreateEngine(appDomain)*, it throws an Serialization exception of the
Microsoft.Scripting.
*
*
*[3]* I have also added the StrongName of the assembly to de Evidence using:
*
*
*
evidence.AddHost(CreateStrongName(Assembly.GetAssembly(typeof(TestingAssembly.FileFactory))));
*
*
*
but it doesn't work.

*[4]* I have subclassified my class *FileFactory* with MarshalByRefObject
class, then I have created another appDomain with all the permissions. Then
I create an instance of this class *FileFactory *using:
*
*
*FileFactory aFileFactory =
(FileFactory)appDomain.CreateInstanceAndUnwrap("TestingAssembly",
"TestingAssembly.FileFactory")*

and finally, I have set o the scope the variable *aFileFactory*
*
*
*scope.SetVariable("aFileFactory", aFileFactory);*
*
*
but when I try to create or delete a file previously created, it doesn't
work.

*[5]* I had to add the attribute to the assembly to allow Partially Trusted
Callers

[assembly: AllowPartiallyTrustedCallers]

and the code is executed, but the AppDomain where the script is execute
applies its security policy without taking into account the AppDomain where
the object have been instantiated.

*[6]* Here is an example of a test that probably will clarify what I am
trying to do.

*AppDomain appDomain =
TestSupportMethods.CreateFullTrustSandboxedAppDomain();*
*FileFactory aFileFactory =
(FileFactory)appDomain.CreateInstanceAndUnwrap("TestingAssembly",
TestingAssembly.FileFactory");*
*
*
*// Here the file is created and then deleted, so it means that the
FullTrustSandboxed allows to create files.*
*aFileFactory.createFile();*
*aFileFactory.deleteFile();*
*string pythonCode = @"aFileFactory.createFile()";*
*ScriptEngine engine =
Python.CreateEngine(TestSupportMethods.CreateSafeSandboxedAppDomainWithEvidence());
*
*ScriptSource source = engine.CreateScriptSourceFromString(pythonCode);*
*ScriptScope scope = engine.CreateScope();*
*scope.SetVariable("aFileFactory", aFileFactory);*
*source.Execute(scope);*

It throws...

*System.Security.SecurityException: Request for the permission of type
'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089' failed..
*

Well, sorry about the size of the email.

Please let me know if you have new ideas, I will do my best to test them.

Regards,
Nicolas


On Mon, Nov 9, 2009 at 7:44 PM, Dino Viehland <dinov at microsoft.com> wrote:

>  Couple of options spring to mind:
>
> 1.       Setup evidence such that your assembly is given full trust.  I
> believe you had the start of this in your other code where you were adding
> some strong name evidence.  You should be able to search the web for normal
> .NET partial trust scenarios for getting this right.
>
> 2.       Setup your object model so that it is a MarshalByRefObject which
> lives in another app domain.  You can then expose the remote object to the
> partial trust app domain via SetVariable.
>
>
>
> As far as including the DLL – you can call LoadAssembly on the
> ScriptRuntime and give it your assembly.  Then the user can import all of
> the types from your DLL as they need them.  That won’t work w/ #2 though.
> Alternately you can implement IAttributesCollection (or use a dynamic object
> in 2.6 although IAC is still supported) and create a scope w/ that as the
> backing storage.  Then you’ll be able to lazily resolve the members rather
> than eagerly populating them - although you still need some code to lazily
> resolve them.
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Monday, November 09, 2009 7:49 AM
>
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Hi all again, I am still working with the same problem.
>
>
>
> Now I am creating the appDomain in this way by recommendation of Dino:
>
>
>
>         *public static AppDomain CreateSandboxAppDomain()*
>
> *        {*
>
> *            AppDomainSetup anAppDomainSetup = new AppDomainSetup();*
>
> *            anAppDomainSetup.ApplicationBase =
> AppDomain.CurrentDomain.BaseDirectory;*
>
> *            anAppDomainSetup.ApplicationName = "Testing";*
>
> *            Evidence evidence = new Evidence();*
>
> *            evidence.AddHost(new Zone(SecurityZone.Internet));*
>
> *            *
>
> *            AppDomain aSandboxedDomain = AppDomain.CreateDomain("Test
> Domain", *
>
> *
>  evidence, *
>
> *
>  anAppDomainSetup);*
>
> *            *
>
> *            return aSandboxedDomain;*
>
> *        }*
>
>
>
> Now it is working but I have security restrictions over some .dll that I
> want to have full trusted permissions. I am trying to do this:
>
>
>
> *string aPythonScript =*
>
> *@"aDocument = CDLDocument()*
>
> *aFigure = TextBlock(1, 'type 1')*
>
> *anotherFigure = TextBlock(2, 'type 2')*
>
> *aDocument.AddFigure(aFigure)*
>
> *aDocument.AddFigure(anotherFigure)*
>
> *aList = aDocument.Figures*
>
> *";*
>
>
>
> *ScriptSource source = engine.CreateScriptSourceFromString(aPythonScript);
> *
>
> *ScriptScope scope = engine.CreateScope();*
>
> *            *
>
> *scope.SetVariable("CDLDocument", typeof(CDLDocument));*
>
> *scope.SetVariable("TextBlock", typeof(TextBlock));*
>
> *source.Execute(scope);*
>
>
>
> This is throwing the  System.Security.SecurityException.
>
>
>
> 1. How can I give full trusted to a specific dll in an AppDomain?
>
>
>
> 2. How can I include a .dll to the scope instead of do a SetVariable for
> each type which I have to manage from the python script?
>
>
>
> Thanks!
>
> Nicolás
>
>
>
> 2009/11/6 Nicolás Buttarelli <nbuttarelli at gmail.com>
>
> Hi,
>
> On Fri, Nov 6, 2009 at 1:07 AM, Dino Viehland <dinov at microsoft.com> wrote:
>
> So you’ve run this as a standalone program and it’s failing?  In the
> standalone app are all of the IronPython and DLR DLLs present
> (IronPython.dll, IronPython.modules.dll, Microsoft.Scripting.Core.dll,
> Microsoft.Scripting.dll, Microsoft.Dynamic.dll and
> Micrsoft.Scripting.Extensionattribute.dll)?
>
> Yes I have all this dlls present.
>
>
>
> A slightly modified version of this, dropping the strong name, works just
> fine for me:
>
>
>
> using System;
>
> using Microsoft.Scripting;
>
> using Microsoft.Scripting.Hosting;
>
> using IronPython.Hosting;
>
> using System.Security;
>
> using System.Security.Permissions;
>
>
>
> class Test {
>
>     public static void Main(string[] args) {
>
>
>
>         PermissionSet aRestrictedPermissionSet = new
> PermissionSet(PermissionState.None);
>
>         aRestrictedPermissionSet.AddPermission(new
> SecurityPermission(SecurityPermissionFlag.Execution));
>
>
>
>         AppDomainSetup domaininfo = new AppDomainSetup();
>
>         domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
>
>
>
>         AppDomain aSandboxedDomain = AppDomain.CreateDomain("Sandboxed
> Domain",
>
>                   AppDomain.CurrentDomain.Evidence,
>
>                   domaininfo,
>
>                   aRestrictedPermissionSet);
>
>
>
>         ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);
>
>         ScriptSource source = engine.CreateScriptSourceFromString("2+2");
>
>         ScriptScope scope = engine.CreateScope();
>
>         Console.WriteLine(source.Execute(scope));
>
>
>
>     }
>
> }
>
>
> Great, I will try this after university. Thanks!
>
>  Compile with:
>
>
>
> csc test.cs /r:Microsoft.Scripting.Core.dll /r:Microsoft.Scripting.dll
> /r:IronPython.dll
>
>
>
> And run and it prints 4.  Does that not work for you?
>
>
>
> We also have a different way we do this in our test suite which also works:
>
>
>
>             AppDomainSetup info = new AppDomainSetup();
>
>             info.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
>
>             info.ApplicationName = "Test";
>
>             Evidence evidence = new Evidence();
>
>             evidence.AddHost(new Zone(SecurityZone.Internet));
>
>             AppDomain newDomain = AppDomain.CreateDomain("test", evidence,
> info);
>
>
>
>             // create runtime in partial trust...
>
>             ScriptRuntime runtime = Python.CreateRuntime(newDomain);
>
>
>
>             // get the Python engine...
>
>             ScriptEngine engine = runtime.GetEngine("py");
>
>
> This make sense too, I will try it. Thanks again.
>
>
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Thursday, November 05, 2009 11:18 AM
>
>
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Again, thanks everyone for your help.
>
>
>
> But.. I bring bad news. This is still not working and it doesn't depend on
> the Test environment.
>
>
>
> I create another proyect, a Form project, with one button which executes
> the following code:
>
>
>
>  // Creating the permission set to grant other assemblies
>
> PermissionSet aRestrictedPermissionSet = new
> PermissionSet(PermissionState.None);
>
> aRestrictedPermissionSet.AddPermission(new
> SecurityPermission(SecurityPermissionFlag.Execution));
>
>
>
> AppDomainSetup domaininfo = new AppDomainSetup();
>
> domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
>
>
>
> List<StrongName> strongNameList = new List<StrongName>();
>
> strongNameList.Add(CreateStrongName(Assembly.GetExecutingAssembly()));
>
>
>
> AppDomain aSandboxedDomain = AppDomain.CreateDomain("Sandboxed Domain",
>
>
>                AppDomain.CurrentDomain.Evidence,
>
>
>                domaininfo,
>
>
>                aRestrictedPermissionSet,
>
>
>                strongNameList.ToArray<StrongName>());
>
>
>
> ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);
>
> ScriptSource source = engine.CreateScriptSourceFromString(pythonScript);
>
> ScriptScope scope = engine.CreateScope();
>
> source.Execute(scope);
>
>
>
> It throws this error:
>
> Type is not resolved for member
> 'Microsoft.Scripting.Hosting.ScriptRuntimeSetup,Microsoft.Scripting,
> Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
>
>
>
> I used the fuslogvw application to see if the Microsoft.Scripting is
> loaded, an it is.
>
>
>
> What seems strange for me is that anyone has tried this before. I hope to
> find some more help here.
>
>
>
> Regards,
>
> Nicolas
>
>
>
>
>
> On Wed, Nov 4, 2009 at 7:36 PM, Shri Borde <Shri.Borde at microsoft.com>
> wrote:
>
> http://www.dev102.com/2008/03/22/3-ways-to-run-nunit-from-visual-studio/has some info about test projects and appbase problems.
>
>
>
> You can also use fuslogvw (
> http://msdn.microsoft.com/en-us/library/e74a18c4(VS.71).aspx)<http://msdn.microsoft.com/en-us/library/e74a18c4%28VS.71%29.aspx%29>to see why Microsoft.Scripting.dll is failing to load.
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Dino Viehland
> *Sent:* Tuesday, November 03, 2009 1:52 PM
>
>
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Test projects are weird and somehow you don’t end up inheriting the
> application base.  This seems to work though:
>
>
>
>             AppDomainSetup setup = new AppDomainSetup();
>
>             setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
>
>             AppDomain aSandboxedDomain = AppDomain.CreateDomain("Sandboxed
> Domain", null, setup);
>
>             ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);
>
>             ScriptSource source =
> engine.CreateScriptSourceFromString("2+2");
>
>             ScriptScope scope = engine.CreateScope();
>
>             Console.WriteLine(source.Execute(scope));
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Tuesday, November 03, 2009 1:30 PM
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> I have create a new "Test Project" and an Unit Test class in order to test
> the following code inside:
>
>
>
> AppDomain aSandboxedDomain = AppDomain.CreateDomain("Sandboxed Domain");
>
> ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);
>
> ScriptSource source = engine.CreateScriptSourceFromString(pythonScript);
>
> ScriptScope scope = engine.CreateScope();
>
> source.Execute(scope);
>
>
>
>
>
> I have add the references:
>
>
>
> - IronPython
>
> - Microsoft.Scripting
>
> - Microsoft.ScriptingCore
>
>
>
> But it still not working and throwing the
> same System.Runtime.Serialization.SerializationException: Type is not
> resolved for member
> 'Microsoft.Scripting.Hosting.ScriptRuntimeSetup,Microsoft.Scripting.
>
>
>
> Any ideas?
>
>
>
>
>
> 2009/11/3 Nicolás Buttarelli <nbuttarelli at gmail.com>
>
> Thanks Shri, I will try.
>
>
>
> In addition, I found this open issue:
> http://dlr.codeplex.com/WorkItem/View.aspx?WorkItemId=2816. I think that
> it is related.
>
>
>
> On Tue, Nov 3, 2009 at 9:29 PM, Shri Borde <Shri.Borde at microsoft.com>
> wrote:
>
> I think this happens if the new appdomain cannot load the required
> assembly. By default, the new appdomain should inherit its BaseDirectory
> property from the creating domain and should be able to load
> Microsoft.Scripting.dll. Is your exe and all the dlls in the same folder? If
> not, can you try to put all assemblies in the same folder (or in the GAC) to
> see if it works? If that works, you can then figure out how to configure the
> new appdomain such that it can load Microsoft.Scripting.dll. There may be
> some setting in AppDomainSetup, or you could hook the AssemblyResolve event…
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Tuesday, November 03, 2009 12:08 PM
>
>
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Hi again, thanks for your clear response.
>
>
>
> I was trying to do what you proposed but it is not working. I am receiving
> an exception:
>
>
>
> *Test method
> CadworX3WCFRestTest.IronPython.SafeScriptExecutionTest.writingAFileTest
> threw exception:  System.Runtime.Serialization.SerializationException: Type
> is not resolved for member
> 'Microsoft.Scripting.Hosting.ScriptRuntimeSetup,Microsoft.Scripting,
> Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'..*
>
> I tried to find a solution but I couldn't. This is the minimal code that I
> am running to get this exception (I have removed all the security stuff but
> apparently that does not resolve the problem):
>
>
>
> *AppDomain aSandboxedDomain = AppDomain.CreateDomain("Sandboxed Domain");*
>
>
>
> *ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);*
>
> *ScriptSource source = engine.CreateScriptSourceFromString(pythonScript);*
>
> *SriptScope scope = engine.CreateScope();*
>
> *source.Execute(scope);*
>
>
>
> The exception is thronged in this line:
>
> *ScriptEngine engine = Python.CreateEngine(aSandboxedDomain);*
>
>
>
>
>
> Do you have any idea which could be the problem?
>
>
>
> Thanks again,
>
> Nicolas
>
>
>
> On Mon, Nov 2, 2009 at 10:25 PM, Dino Viehland <dinov at microsoft.com>
> wrote:
>
> Assuming the app domain is setup properly then there’s no way for the
> Python code to elevate permissions (modulo CLR security bugs which are few
> and far between).  This is because IronPython its self is 100% security
> transparent and does not affect any security decisions or assert any form of
> trust – so it’s all up to the CLR to limit permissions.  So for example
> while you can access the file object, or import ctypes, or call various
> other Python APIs which would require trust you’ll get a security exception
> from the CLR when you don’t have permissions to do something.
>
>
>
> For more complex scenarios you might also have an object model which you
> expose to the application and inject in via its scope.  Once you’ve done
> that you’ll want to make sure that the object model is also secure.
>
>
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Monday, November 02, 2009 1:20 PM
> *To:* Discussion of IronPython
> *Subject:* Re: [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Thanks for your response.
>
>
>
> But what happens with the python code? Does not exist a way to write some
> scripts that can do some damage to my app, the server, the database, etc?
>
>
>
> Thanks again,
>
> Nicolas
>
>
>
> On Mon, Nov 2, 2009 at 9:41 PM, Dino Viehland <dinov at microsoft.com> wrote:
>
> After creating your app domain you can do:
>
>
>
> ScriptEngine engine = Python.CreateEngine(someAppDomain);
>
>
>
> And then the rest of your code should work as it’s written.
>
>
>
>
>
> *From:* users-bounces at lists.ironpython.com [mailto:
> users-bounces at lists.ironpython.com] *On Behalf Of *Nicolás Buttarelli
> *Sent:* Monday, November 02, 2009 12:39 PM
> *To:* users at lists.ironpython.com
> *Subject:* [IronPython] Safe execution of python scripts on my .net
> application
>
>
>
> Sorry, I don't know if my previous message have arrived. So, here it is:
>
>
>
>
>
> Hello all,
>
>
>
> I am starting with python and I would like to add to my web application
> some web services. This services will allow the different clients of my
> application to execute some python scripts.
>
>
>
> I would like to know if someone did this before and how can I do this in a
> secure way. I mean, how can I do to restrict the environment where the
> scripts will be executed.
>
>
>
> In .net I can do this using the AppDoman and setting the permission set.
>
>
>
> AppDomain.CreateDomain( string friendlyName,
>                         Evidence securityInfo,
>                         AppDomainSetup info,
>                         PermissionSet grantSet,
>                         params StrongName[] fullTrustAssemblies);
>
>
>
>
>
> Is there a way to do the same with my python scripts?
>
>
>
> I am running them using this:
>
>
>
> ScriptEngine engine = Python.CreateEngine();
>
> ScriptSource source = engine.CreateScriptSourceFromString(scriptAsString);
>
> ScriptScope scope = engine.CreateScope();
>
> source.Execute(scope);
>
>
>
> Thanks in advance.
>
> Nicolas
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
>
>
>
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ironpython.com/pipermail/users-ironpython.com/attachments/20091201/70c66ddf/attachment-0001.htm>


More information about the Users mailing list