[Python-Dev] Security capabilities in Python
Jp Calderone
exarkun at divmod.com
Sat Apr 9 11:02:23 CEST 2005
On Sat, 9 Apr 2005 00:13:40 -0500 (CDT), Ka-Ping Yee <python-dev at zesty.ca> wrote:
>On Fri, 8 Apr 2005, Eyal Lotem wrote:
> > I would like to experiment with security based on Python references as
> > security capabilities.
>
> This is an interesting and worthwhile thought. Several people
> (including myself) have talked about the possibility of doing
> this in the past. I believe the two problems you mention can be
> addressed without modifying the Python core.
>
> > * There is no way to create secure proxies because there are no
> > private attributes.
>
> Attributes are not private, but local variables are. If you use
> lexical scoping to restrict variable access (as one would in
> Scheme, E, etc.) you can create secure proxies. See below.
>
> > * Lots of Python objects are reachable unnecessarily breaking the
> > principle of least privelege (i.e: object.__subclasses__() etc.)
>
> True. However, Python's restricted execution mode prevents access
> to these attributes, allowing you to enforce encapsulation. (At
> least, that is part of the intent of restricted execution mode,
> though currently we do not make official guarantees about it.)
> Replacing __builtins__ activates restricted execution mode.
>
> Here is a simple facet function.
>
> def facet(target, allowed_attrs):
> class Facet:
> def __repr__(self):
> return '<Facet %r on %r>' % (allowed_attrs, target)
> def __getattr__(self, name):
> if name in allowed_attrs:
> return getattr(target, name)
> raise NameError(name)
> return Facet()
>
> def restrict():
> global __builtins__
> __builtins__ = __builtins__.__dict__.copy()
>
> # Here's an example.
>
> list = [1, 2, 3]
> immutable_facet = facet(list, ['__getitem__', '__len__', '__iter__'])
>
> # Here's another example.
>
> class Counter:
> def __init__(self):
> self.n = 0
>
> def increment(self):
> self.n += 1
>
> def value(self):
> return self.n
>
> counter = Counter()
> readonly_facet = facet(counter, ['value'])
>
> If i've done this correctly, it should be impossible to alter the
> contents of the list or the counter, given only the immutable_facet
> or the readonly_facet, after restrict() has been called.
>
> (Try it out and let me know if you can poke holes in it...)
>
> The upshot of all this is that i think you can do secure programming
> in Python if you just use a different style. Unfortunately, this
> style is incompatible with the way classes are usually written in
> Python, which means you can't safely use much of the standard library,
> but i believe the language itself is not fatally flawed.
>
Does using the gc module to bypass this security count? If so:
exarkun at boson:~$ python -i facet.py
>>> import gc
>>> c = readonly_facet.__getattr__.func_closure[1]
>>> r = gc.get_referents(c)[0]
>>> r.n = 'hax0r3d'
>>> readonly_facet.value()
'hax0r3d'
>>>
This is the easiest way of which I know to bypass the use of cells as a security mechanism. I believe there are other more involved (and fragile, probably) ways, though.
Jp
More information about the Python-Dev
mailing list