Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ModuleSecurityInfo('os').declarePublic('environ') allows os.system #12

Closed
stephan-hof opened this issue Dec 18, 2015 · 4 comments
Closed
Assignees
Labels

Comments

@stephan-hof
Copy link
Member

as mentioned above I have the following line in one of my zope Products.

ModuleSecurityInfo('os').declarePublic('environ')

Unfortunately in a PythonScript inside Zope, which should run under restricted python, I write code like this without getting an Unauthorized exception. Instead the os.system is happily executed, giving a lot of 'fun' to the users of my system :)

import os
os.system('ls /')

I looked a bit through the code and the following function in SecurityInfo.py got my attention.

class _ModuleSecurityInfo(SecurityInfo):
    """Encapsulate security information for modules."""

    __call____roles__ = ACCESS_PRIVATE
    def __call__(self, name, value):
        """Callback for __allow_access_to_unprotected_subobjects__ hook."""
        access = self.names.get(name, _marker)
        if access is not _marker:
            return access == ACCESS_PUBLIC
        return getattr(self, 'access', 0)

The interesting line is getattr(self, 'access', 0). Somehow self takes part in acquisition with the os module as parent.

print Acquisition.aq_chain(self) 
[<AccessControl.SecurityInfo._ModuleSecurityInfo object at 0xa25c28c>, <module 'os' from '/usr/lib/python2.7/os.pyc'>]

So, self having no attribute 'access', Acquisition jumps back to the os module which has an attribute being os.access

Access control evaluates os.access as True which means 'system' is allowed.

I don't have a big clue how AccessControl works, so its hard for me to say what is the 'appropriate' fix for this. Right now I changed the the __call__ method to this:

    __call____roles__ = ACCESS_PRIVATE
    def __call__(self, name, value):
        """Callback for __allow_access_to_unprotected_subobjects__ hook."""
        access = self.names.get(name, _marker)
        if access is not _marker:
            return access == ACCESS_PUBLIC

        me = Acquisition.aq_base(self)
        return getattr(me, 'access', 0)
@tseaver tseaver added the bug label Dec 18, 2015
@tseaver tseaver self-assigned this Dec 18, 2015
@tseaver
Copy link
Member

tseaver commented Dec 18, 2015

Thank you for the report! I believe your analysis is correct, and that acquiring access cannot be intended. Rather than use aq_base, I propose that we update SecurityInfo such that it sets access to False by default at the class level. I will test this change with a full Zope instance to ensure it doesn't break stuff.

@stephan-hof
Copy link
Member Author

Hi,

I'll will apply your proposed change also to my Zope instance and let you know if something breaks.

@tseaver
Copy link
Member

tseaver commented Dec 21, 2015

After checking: Setting access = False in the SecurityInfo base class causes tests to fail (and likely breaks a bunch of stuff). Setting it in the derived _ModuleSecurityInfo class lets them all pass, but should still fix your issue.

tseaver added a commit that referenced this issue Dec 21, 2015
'SecurityInfo._ModuleSecurityInfo' should not grant or deny access based on
the presence / value of an 'access' attribute in the wrapped module.

Closes #12.
tseaver added a commit that referenced this issue Dec 21, 2015
@tseaver
Copy link
Member

tseaver commented Dec 21, 2015

via e47723e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants