Python Object Encapsulation Security

I have a question, and my decision on choosing Python as a possible language for a larger project depends on the answer - which I cannot come up with myself:

We all know that Python has no real encapsulation of objects, so there is nothing like the "private" properties of an object. Regarding this problem, Guido van Rossum says that you can access the hidden parts of an extraneous object without being “authorized,” and “we are all adults,” “just don't do this.” I can do this very well as long as the software that I write is in my own hand, so I am responsible for my own mistakes and just can try to avoid such things.

BUT - and here is my question: What should I do if I provide a plugin framework with some plugins that have some extension points, and many of the plugins are OTHER people, maybe those that I can’t completely trust.

How to prevent access to the internal components of my structure from the plugin?

Is there a way to achieve this or is it the only way to use Python with the confidence that no one will abuse my API?

+7
python security encapsulation
source share
1 answer

You should never rely on private , public , etc. to ensure security (as in the section "Protection against malicious code and external threats"). They are designed so that the programmer does not shoot in the leg, and not as a (computer) security measure. You can also easily access the private member fields of C ++ objects if you bypass static compiler checks and go directly to memory, but can you say that C ++ lacks true encapsulation?

That way, you would never use private or protected as a security measure against malicious plugins in C ++ or Java, and I also assume that C #.

It’s best to run the plugins in a separate process and expose the main API via IPC / RPC or even a web service or run them in the sandbox (according to what @MarkHildreth indicated). In addition, you can set up a certification and signature process for your plugins so that you can view and filter potentially harmful plugins before they even get distributed.

Note:

In fact, you can achieve true encapsulation with lexical closures:

 def Foo(param): param = [param] # because `nonlocal` was introduced only in 3.x class _Foo(object): @property def param(self): return param[0] @param.setter def param(self, val): param[0] = val return _Foo() foo = Foo('bar') print foo.param # bar foo.param = 'baz' print foo.param # baz # no way to access `foo._param` or anything 

... but even then the value is actually still relatively easily accessible through reflection:

 >>> foo.__class__.param.fget.__closure__[0].cell_contents[0] = 'hey' >>> foo.param 'hey' 

... and even if this is not possible, we will still be ctypes with ctypes , which allows direct access to memory, bypassing any remaining cosmetic "restrictions":

 import ctypes arr = (ctypes.c_ubyte * 64).from_address(id(foo)) 

and now you can just assign arr or read it; although you have to work hard to traverse the pointers from there to the actual memory location where .param is stored, but this proves the point.

+16
source share

All Articles