Hi All, I know we have security proxies nowadays and I'm hoping these have made things much more efficient that the old Zope 2 way of doing things (anyone have any ideas on this?) but is there still a way of running a piece of python in an environment where imports are controlled and "dangerous" builtins (ie: ones that would allow you to circumvent the security policy) are restricted? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote:
I know we have security proxies nowadays and I'm hoping these have made things much more efficient that the old Zope 2 way of doing things (anyone have any ideas on this?) but is there still a way of running a piece of python in an environment where imports are controlled and "dangerous" builtins (ie: ones that would allow you to circumvent the security policy) are restricted?
Okay, I see two potentially interesting things: http://svn.zope.org/zope.security/trunk/src/zope/security/untrustedpython/ and http://svn.zope.org/RestrictedPython/trunk/src/RestrictedPython/ Are either of these still in use/maintained? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Chris Withers wrote:
Chris Withers wrote:
I know we have security proxies nowadays and I'm hoping these have made things much more efficient that the old Zope 2 way of doing things (anyone have any ideas on this?) but is there still a way of running a piece of python in an environment where imports are controlled and "dangerous" builtins (ie: ones that would allow you to circumvent the security policy) are restricted?
Okay, I see two potentially interesting things:
http://svn.zope.org/zope.security/trunk/src/zope/security/untrustedpython/
and
http://svn.zope.org/RestrictedPython/trunk/src/RestrictedPython/
Are either of these still in use/maintained?
Both are. RestrictedPython is still used in Zope2. The 'untrustedpython' bit has lots of dependencies, and so is available as an "extra" for zope.security, e.g.: $ bin/easy_install --index-url=http://download.zope.org/zope3.4 \ zope.security[untrustedpython] My guess is that the dependency furball there needs untangling; however, that command line *does* get the pacakge installed. Tres. - -- =================================================================== Tres Seaver +1 540-429-0999 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFHQa7u+gerLs4ltQ4RAkYyAJ9fNyKTueny8Uy3ArmpHJxsmlFZrwCffE31 av7nmTBBMR9j13QygW3rYVo= =3see -----END PGP SIGNATURE-----
Tres Seaver wrote:
Both are. RestrictedPython is still used in Zope2.
Ah, so RestrictedPython is actually what's used for Script (Python)'s in current Zope 2 releases? That's a big positive selling point for me ;-) I think RestrictedPython is also "used" (ie: bundled with) Zope 3 given the comments, for example,here: http://svn.zope.org/RestrictedPython/trunk/src/RestrictedPython/Eval.py?rev=...
The 'untrustedpython' bit has lots of dependencies, and so is available as an "extra" for zope.security, e.g.:
...the warning at the top of this file scares me: http://svn.zope.org/zope.security/trunk/src/zope/security/untrustedpython/in... Also, the last changes were made over 3 years ago: http://svn.zope.org/zope.security/trunk/src/zope/security/untrustedpython/?r... including the ominous phrase: """ even though it's not actually used, I was afraid that someone would try to use it """ ;-) So, I'm guessing RestrictedPython is the one to aim for? Anyone have an opinion? cheers. Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote:
Tres Seaver wrote:
Both are. RestrictedPython is still used in Zope2.
Ah, so RestrictedPython is actually what's used for Script (Python)'s in current Zope 2 releases?
Yes, it's a low-level compiler for Python code that replaces certain operations such as getattr with respective guards. You'll have to provide such guards, though. "Script (Python)" is based on Shared.DC.Scripts which implements such guards that do checks based on AccessControl. It looks like zope.security.untrustedpython integrates RestrictedPython with zope.security.
I think RestrictedPython is also "used" (ie: bundled with) Zope 3 given the comments, for example,here:
http://svn.zope.org/RestrictedPython/trunk/src/RestrictedPython/Eval.py?rev=...
Yup, it's bundled and since Zope 2 and 3 were in different trees, we had a small fork that was reunited in that checkin.
So, I'm guessing RestrictedPython is the one to aim for?
No idea what you need...
Philipp von Weitershausen wrote:
Yes, it's a low-level compiler for Python code that replaces certain operations such as getattr with respective guards. You'll have to provide such guards, though. "Script (Python)" is based on Shared.DC.Scripts which implements such guards that do checks based on AccessControl.
It looks like zope.security.untrustedpython integrates RestrictedPython with zope.security.
Ahhhh, I see now...
So, I'm guessing RestrictedPython is the one to aim for?
No idea what you need...
http://mail.python.org/pipermail/python-list/2007-November/466438.html Out of interest, if all non-standard objects (ie: content) are wrapped in security proxies, do getattr and setattr still need to be overridden? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
On 19 Nov 2007, at 20:26 , Chris Withers wrote:
So, I'm guessing RestrictedPython is the one to aim for? No idea what you need...
http://mail.python.org/pipermail/python-list/2007-November/466438.html
It seems like zope.security does exactly what you need (e.g. user code shouldn't have to import anything as long as you pass proxied objects). <shameless plug> My book's chapter 21 does a complete walk- through of the zope.security system.</shamesless plug>
Out of interest, if all non-standard objects (ie: content) are wrapped in security proxies, do getattr and setattr still need to be overridden?
Nope.
Philipp von Weitershausen wrote:
On 19 Nov 2007, at 20:26 , Chris Withers wrote:
So, I'm guessing RestrictedPython is the one to aim for? No idea what you need...
http://mail.python.org/pipermail/python-list/2007-November/466438.html
It seems like zope.security does exactly what you need (e.g. user code shouldn't have to import anything as long as you pass proxied objects).
Indeed, but how do you prevent importing and insecure builtins like "open" without RestrictedPython? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
On 20 Nov 2007, at 00:15 , Chris Withers wrote:
Philipp von Weitershausen wrote:
On 19 Nov 2007, at 20:26 , Chris Withers wrote:
So, I'm guessing RestrictedPython is the one to aim for? No idea what you need...
http://mail.python.org/pipermail/python-list/2007-November/466438.html It seems like zope.security does exactly what you need (e.g. user code shouldn't have to import anything as long as you pass proxied objects).
Indeed, but how do you prevent importing and insecure builtins like "open" without RestrictedPython?
Well, they can only use the builtins you give them, right? And the 'import' statement can be influenced with import hooks, AFAIK. I don't knwo this for sure, though, so maybe you do need RestrictedPython after all.
Philipp von Weitershausen wrote:
On 20 Nov 2007, at 00:15 , Chris Withers wrote:
Philipp von Weitershausen wrote:
On 19 Nov 2007, at 20:26 , Chris Withers wrote:
So, I'm guessing RestrictedPython is the one to aim for? No idea what you need...
http://mail.python.org/pipermail/python-list/2007-November/466438.html It seems like zope.security does exactly what you need (e.g. user code shouldn't have to import anything as long as you pass proxied objects).
Indeed, but how do you prevent importing and insecure builtins like "open" without RestrictedPython?
Well, they can only use the builtins you give them, right? And the 'import' statement can be influenced with import hooks, AFAIK. I don't knwo this for sure, though, so maybe you do need RestrictedPython after all.
One bit that might be problematic is 'proxy leaking'. I imagine if you use this you're going to leak proxied objects into the rest of your system whenever you make a call into your system. Traditional Zope 2 doesn't work that way: as soon as you make a call from your Python script, the underlying code that is being called is trusted. No proxies anywhere (well, except the ubiquitous acquisition proxies..). I don't know whether this could be a problem for your use case. You could solve it by using a special kind of proxy that proxies everything that you receive *into* the Python script from return values but removes the proxy from any arguments you pass in when you make a call. Regards, Martijn
Martijn Faassen wrote:
One bit that might be problematic is 'proxy leaking'. I imagine if you use this you're going to leak proxied objects into the rest of your system whenever you make a call into your system.
Actually, I'm hoping I can have anything content-object like "always proxied". One of my original two requirements (which I linked to before) is the ability for "the system" to just work with objects and have them complain if you're not allowed to access them, rather than having to remember that just because you're in "trusted code" the user that the trusted code is executing on behalf of will "see everything"...
Traditional Zope 2 doesn't work that way: as soon as you make a call from your Python script, the underlying code that is being called is trusted. No proxies anywhere (well, except the ubiquitous acquisition proxies..).
Indeed, sometimes this is handy, sometimes it causes problems... cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Hi there, On Nov 20, 2007 11:24 AM, Chris Withers <chris@simplistix.co.uk> wrote: [snip]
Traditional Zope 2 doesn't work that way: as soon as you make a call from your Python script, the underlying code that is being called is trusted. No proxies anywhere (well, except the ubiquitous acquisition proxies..).
Indeed, sometimes this is handy, sometimes it causes problems...
There will be a problem if proxies get into subsystems without any security declarations. Most security policies should forbid access in that case. You might be surprised how many things you'll need to add security declarations for. In my experience this seriously kills development speed early on in the project. Regards, Martijn
Martijn Faassen wrote:
There will be a problem if proxies get into subsystems without any security declarations. Most security policies should forbid access in that case.
You might be surprised how many things you'll need to add security declarations for. In my experience this seriously kills development speed early on in the project.
I haven't decided what security policy I'll be using yet, so this may or may not be a problem ;-) As an aside, has anyone built something like an interactive shell that runs with the restricted compiler? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Philipp von Weitershausen wrote:
Indeed, but how do you prevent importing and insecure builtins like "open" without RestrictedPython?
Well, they can only use the builtins you give them, right?
Hmm, not sure what you mean by this? How do you choose what builtins to give them?
And the 'import' statement can be influenced with import hooks, AFAIK.
ut surely your untrusted python script could then just go and undo those same hooks?
I don't knwo this for sure, though, so maybe you do need RestrictedPython after all.
I have a feeling I do, but I'd like to check ;-) cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote at 2007-11-20 10:21 +0000:
Philipp von Weitershausen wrote:
Indeed, but how do you prevent importing and insecure builtins like "open" without RestrictedPython?
Well, they can only use the builtins you give them, right?
Hmm, not sure what you mean by this? How do you choose what builtins to give them?
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them. -- Dieter
Dieter Maurer wrote:
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them.
unfortunately that still leaves the import problems, correct? cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote at 2007-11-20 23:55 +0000:
Dieter Maurer wrote:
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them.
unfortunately that still leaves the import problems, correct?
The "import" "command" is mapped to the "__import__" builtin. Thus, changing the "__import__" builtin.... -- Dieter
Dieter Maurer wrote:
Chris Withers wrote at 2007-11-20 23:55 +0000:
Dieter Maurer wrote:
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them. unfortunately that still leaves the import problems, correct?
The "import" "command" is mapped to the "__import__" builtin.
Thus, changing the "__import__" builtin....
Ah, fantastic, so if I supply a very limited namespace to the environment, with my own __builtins__ and __import__, and where all objects I worry about are proxied, I should be okay not to use restricted python at all? If so, that would be uber cool :-) Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Dieter Maurer wrote:
Chris Withers wrote at 2007-11-20 23:55 +0000:
Dieter Maurer wrote:
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them. unfortunately that still leaves the import problems, correct?
The "import" "command" is mapped to the "__import__" builtin.
Thus, changing the "__import__" builtin....
Hmmm, looking into this more. I think fiddling with supplying __builtins__ and __import__ is susceptible to those being deleted from the local or global namespace and so being replaced by ones from the above namespace. Am I right in seeing those as security risks? These seem to be some of the reasons rexec and bastion were dropped from python: http://bugs.python.org/issue577530 http://mail.python.org/pipermail/python-dev/2002-December/031160.html cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote at 2007-11-22 17:08 +0000:
Dieter Maurer wrote:
Chris Withers wrote at 2007-11-20 23:55 +0000:
Dieter Maurer wrote:
You execute their code in a "globals" the "__builtins__" of which contains precisely the builtins you want to give them. unfortunately that still leaves the import problems, correct?
The "import" "command" is mapped to the "__import__" builtin.
Thus, changing the "__import__" builtin....
Hmmm, looking into this more. I think fiddling with supplying __builtins__ and __import__ is susceptible to those being deleted from the local or global namespace and so being replaced by ones from the above namespace.
Am I right in seeing those as security risks? These seem to be some of the reasons rexec and bastion were dropped from python:
There have been reasons why Python no longer promisses a secure restricted environment....
When you look carefully, you see that this problem has been fixed.
http://mail.python.org/pipermail/python-dev/2002-December/031160.html
You handle this with security proxied objects, right? Security questions are very delicate. Nobody will probably give you a garantee that the approach is really safe. -- Dieter
Dieter Maurer wrote:
Security questions are very delicate. Nobody will probably give you a garantee that the approach is really safe.
This is why my gut feel is to stick with RestrictedPython as it has been pretty well battle tested :-) cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
participants (5)
-
Chris Withers -
Dieter Maurer -
Martijn Faassen -
Philipp von Weitershausen -
Tres Seaver