Creating a capabilities-based restricted execution system

Sean R. Lynch seanl at chaosring.org
Sat Jan 3 15:48:00 EST 2004


Serge Orlov wrote:
> "Sean R. Lynch" <seanl at chaosring.org> wrote in message news:LmmdnUn4seDeGWuiXTWc-w at speakeasy.net...
> 
>>I've been playing around with Zope's RestrictedPython, and I think I'm
>>on the way to making the modifications necessary to create a
>>capabilities-based restricted execution system. The idea is to strip out
>>any part of RestrictedPython that's not necessary for doing capabilities
>>and do all security using just capabilities.
>>
>>The basic idea behind capabilities is that you don't give any piece of
>>code you don't trust a reference to something you don't want it to have
>>access to. You use proxies instead (E calls them "facets").
> 
> 
> "Don't give" sounds good in theory but fails in practice. You can't prevent
> leakage 100%, so any security system _must_ help programmer to keep
> trusted data away from untrusted code. Do you know that rexec failed
> exactly because it didn't help to prevent leakage?

Hmm, this is good information. I think it will probably change the way 
I've been looking at this.

>>In order to be able to allow untrusted code to create proxy objects, I
>>needed to be able to store a reference to the proxied object in a
>>private attribute.
>>
>>To create private attributes, I'm using "name mangling," where names
>>beginning with X_ within a class definition get changed to
>>_<uuid>_<name>, where the UUID is the same for that class. The UUIDs
>>don't need to be secure because it's not actually possible to create
>>your own name starting with an underscore in RestrictedPython; they just
>>need to be unique across all compiler invocations.
> 
> 
> This is a problem: you declare private attributes whereas you should be
> declaring public attributes and consider all other attributes private. Otherwise
> you don't help prevent leakage. What about doing it this way:
> 
> obj.attr means xgetattr(obj,acc_tuple) where acc_tuple = ('attr',UUID)
> and xgetattr is
> def xgetattr(obj,acc_tuple):
>   if not has_key(obj.__accdict__,acc_tuple):
>     raise AccessException
>   return getattr(obj,acc_tuple[0])
> 
> __accdict__ is populated at the time class or its subclasses are created.
> If an object without __accdict__ is passed to untrusted code it will
> just fail. If new attributes are introduced but not declared in __accdict__
> they are also unreachable by default.

This is very interesting, and you may convince me to use something 
similar, but I don't think you're quite correct in saying that the 
name-mangling scheme declares private attributes; what is the difference 
between saying "not having X_ in front of the attribute makes it public" 
and "having X_ in front of the attribute makes it private?"

>>The nice thing about using this name mangling is that it's only done at
>>compile time and doesn't affect runtime performance. An interesting side
>>effect is that code defined on a class can access private attributes on
>>all descendants of that class, but only ones that are defined by other
>>code on that class, so this isn't a security issue.
>>
>>I was thinking I needed read-only attributes to be able to avoid
>>untrusted code's being able to sabotage the revoke method on a proxy
>>object, but I'm thinking that just keeping around a reference to the
>>revoke method in the original code may be enough.
>>
>>Does anyone think I'm going in completely the wrong direction here? Am I
>>missing anything obvious?
> 
> 
> It depends on what type of security do you want. Did you think about DOS
> and covert channels? If you don't care about that, yeah, you don't miss
> anything obvious. <wink> you should worry whether you miss something
> non-obvious.

I am not (particularly) concerned about DoS because I don't plan to be 
running anonymous code and having to restart the server isn't that big 
of a deal. I do plan to make it hard to accidentally DoS the server, but 
I'm not going to sacrifice a bunch of performance for that purpose. As 
for covert channels, can you give me an example of what to look for?

I am certainly worried about non-obvious things, but my intent wasn't to 
put up a straw man, because if I ask if I'm missing non-obvious things, 
the only possible answer is "of course."

> By the way, did you think about str.encode? Or you are not worried about
> bugs in zlib too?

Well, it'll only take *one* problem of that nature to force me to go 
back to converting all attribute accesses to function calls. On the 
other hand, as long as any problem that allows a user to access 
protected data is actually a in (zlib, etc), I think I'm not going to 
worry about it too much yet. If there is some method somewhere that will 
allow a user access to protected data that is not considered a bug in 
that particular subsystem, then I have to fix it in my scheme, which 
would probably require going back to converting attribute access to 
method calls.



More information about the Python-list mailing list