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

private "special" methods can be (indirectly) accessed by untrusted code #98

Open
d-maurer opened this issue Apr 22, 2020 · 1 comment
Labels

Comments

@d-maurer
Copy link
Contributor

d-maurer commented Apr 22, 2020

The code below constructs a class Protected with private keys and __getitem__ methods and shows how to call these methods indirectly from untrusted code:

from AccessControl.tests.testZopeGuards import TestActualPython
t = TestActualPython("testPython")

from AccessControl.class_init import InitializeClass
from AccessControl.SecurityInfo import ClassSecurityInfo
from ExtensionClass import Base

class Protected(Base):
    security = ClassSecurityInfo()
  
    @security.private
    def keys(self):
        return (1, 2, 3)
  
    @security.private
    def __getitem__(self, key):
        return key

InitializeClass(Protected)

protected = Protected()

access_code="""\
d = {}
d.update(protected)
assert d == {1:1, 2:2, 3:3}
"""

code, g = t._compile_str(access_code, __name__)
g["protected"] = protected
exec(code, g)

The same likely applies to many "special" methods called implicitly by Python (such as __bool__, __index__, __iter__, ...) or methods of Python types. The example above uses dict.update; similar unprotected access is likely possible with list.extend (using __iter__ without protection).

@d-maurer d-maurer added the bug label Apr 22, 2020
@d-maurer
Copy link
Contributor Author

Trying to construct examples for a practical security preach I found hints that the problem might have limited practical importance. I concentrated my research on dict.update and list.extend; dict and list are examples of types which can be used in restricted contexts with almost no restrictions. dict.update can call its argument's keys+__getitem__ or __iter__ without the security checks normally applied in restricted contexts; list.extend can do this with __iter__. In both cases, the result of the unprotected calls arrive in a container (dict or list); access to individual elements of such containers is usually protected and typically will fail unless the accessed element is simple (i.e. of an "allowed type") or public.

This means that a security preach could involve an object maintaining sensitive information accessed via "special" methods (e.g. "keys", "getitem", "iter") which essentially only use (potentially recursively) "simple" types/containers.

A constructed example could be a class providing a mapping interface to a user base where each user is described by a dict or public class instance.

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

1 participant