Python对象封装安全性

时间:2013-10-02 19:31:14

标签: python security encapsulation

我有一个问题,我选择Python作为一个更大项目的可能语言的决定取决于答案 - 我自己无法想出:

我们都知道Python没有真正的对象封装,所以没有像对象的“私有”属性。关于这个问题,Guido van Rossum说,人们可以在不被“允许”的情况下访问异物的隐藏部分,“我们都是成年人”,“就是不要这样做”。 我可以很好地生活,只要我自己编写的软件是我自己的,所以我对自己的错误负责,并且可以尽量避免这样的事情。

但是 - 这是我的问题: 如果我为插件框架提供一些具有一些扩展点的插件,并且许多插件是由其他人,也许是我完全不能信任的插件,那该怎么办呢?

如何防止暴露我的框架内部被插件访问?

有没有办法实现这一点,或者是使用Python的唯一方法是否有人会滥用我的API?

1 个答案:

答案 0 :(得分:17)

您永远不应该真正依赖privatepublic等安全性(如“防范恶意代码和外部威胁”)。它们意味着让程序员不必在脚下射击,而不是作为(计算机)安全措施。您也可以轻松访问C ++对象的私有成员字段,只要您绕过静态编译器检查并直接进入内存,但是您会说C ++缺少真正的封装吗?

因此,您永远不会真正使用privateprotected作为针对C ++和Java中的恶意插件的安全措施,我也假设C#。

最好的办法是在一个单独的进程中运行插件,并通过IPC / RPC甚至Web服务公开核心API,或者在sandbox中运行它们(根据@MarkHildreth指出的那样)。或者,您可以为插件设置认证和签名过程,以便在分发之前查看和过滤掉潜在的恶意插件。

注意:

使用词法闭包实际上可以实现真正的封装:

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

......但即便如此,这个价值实际上仍然可以通过反思轻松获取:

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

......即使这是不可能的,我们仍然会留下ctypes,允许直接访问内存,绕过任何剩余的化妆品“限制”:

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

现在您可以分配到arr或从中读取;虽然你必须努力将指针从那里遍历到存储.param的实际内存位置,但它证明了这一点。