如何保护Python类变量免受邪恶程序员的侵害?

发布于 2025-01-03 06:46:20 字数 2467 浏览 1 评论 0原文

我怎样才能保护我的变量免受这种攻击:

MyClass.__dict__ = {}
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not')

上面更改了变量字典,之后更改所有变量就很简单了。上面的线对于其发挥作用至关重要。如果您的字典的 __setitem__ 进行如下调整,则上述内容不起作用)。

我想强制用户使用我的方法 setProtectedVariable(value) 来更改变量,但我似乎在 Python 2.7 中找不到这样做的方法。有什么想法吗?

如果您从下面的代码中发现其他类似的漏洞,我也很感激(我注意到我还应该将文件名和行号添加到我的 inspect.stack 检查中 myDict.__setitem__)。

这是我到目前为止所尝试过的:

import inspect

class ProtectionTest:

    __myPrivate = 0

    def __init__(self):
        md = myDict()
        setattr(self,'__dict__', md)

    def __setattr__(self, name, val):     
        if name == '__myPrivate':
            print "failed setattr attempt: __myPrivate"
            pass
        elif name == '_ProtectionTest__myPrivate':
            print "failed setattr attempt: _ProtectionTest__myPrivate"  
            pass
        elif name == '__dict__':
            print "failed setattr attempt: __dict__"
            pass
        else: 
            self.__dict__[name] = val             

    def getMyPrivate(self):
        return self.__myPrivate

    def setMyPrivate(self, myPrivate):
        #self.__dict__['_ProtectionTest__stack'] = inspect.stack()[0][1:]
        self.__dict__['_ProtectionTest__myPrivate'] = -myPrivate

class myDict(dict):

    def __init__(self):
        dict.__init__(self)

    def __setitem__(self, key, value):
        if inspect.stack()[1][3] == 'setMyPrivate':
            dict.__setitem__(self,key,value)
        else:
            print "failed dict attempt"
            pass

pt = ProtectionTest()

print "trying to change... (success: 1): "
pt.__myPrivate = 1
print pt.getMyPrivate(), '\n'

print "trying to change... (success: 2): "
pt._ProtectionTest__myPrivate = 2
print pt.getMyPrivate() , '\n'

print "trying to change... (success: 3): "
pt.__dict__['_ProtectionTest__myPrivate'] = 3
print pt.getMyPrivate() , '\n'

print "trying to change the function (success: 4): "
def setMyPrivate(self, myPrivate):
    self.__dict__['_ProtectionTest__myPrivate'] = 4
pt.setMyPrivate = setMyPrivate
pt.setMyPrivate(0)
print pt.getMyPrivate(), '\n'

print "trying to change the dict (success: 5): "
pt.__dict__ = {}
pt.__dict__.__setitem__('_ProtectionTest__myPrivate',5)
print pt.getMyPrivate(), '\n'

print "Still working (correct output = -input = -100): "    
pt.setMyPrivate(100)
print pt.getMyPrivate()  

How can I protect my variables from this kind of attack:

MyClass.__dict__ = {}
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not')

The above changes the variable dictionary and after that it is childs play to change all the variables. The upper line is crucial for this to work. The above does not work if your dictionary's __setitem__ is tweaked like below).

I want to force user to use my method setProtectedVariable(value) to change the variable, but I seem to find no way of doing that in Python 2.7. Any ideas?

I appreciate also if you find other similar holes from the code below (I noticed that I should add also the file name and line number to my inspect.stack check in myDict.__setitem__).

This is what I have tried so far:

import inspect

class ProtectionTest:

    __myPrivate = 0

    def __init__(self):
        md = myDict()
        setattr(self,'__dict__', md)

    def __setattr__(self, name, val):     
        if name == '__myPrivate':
            print "failed setattr attempt: __myPrivate"
            pass
        elif name == '_ProtectionTest__myPrivate':
            print "failed setattr attempt: _ProtectionTest__myPrivate"  
            pass
        elif name == '__dict__':
            print "failed setattr attempt: __dict__"
            pass
        else: 
            self.__dict__[name] = val             

    def getMyPrivate(self):
        return self.__myPrivate

    def setMyPrivate(self, myPrivate):
        #self.__dict__['_ProtectionTest__stack'] = inspect.stack()[0][1:]
        self.__dict__['_ProtectionTest__myPrivate'] = -myPrivate

class myDict(dict):

    def __init__(self):
        dict.__init__(self)

    def __setitem__(self, key, value):
        if inspect.stack()[1][3] == 'setMyPrivate':
            dict.__setitem__(self,key,value)
        else:
            print "failed dict attempt"
            pass

pt = ProtectionTest()

print "trying to change... (success: 1): "
pt.__myPrivate = 1
print pt.getMyPrivate(), '\n'

print "trying to change... (success: 2): "
pt._ProtectionTest__myPrivate = 2
print pt.getMyPrivate() , '\n'

print "trying to change... (success: 3): "
pt.__dict__['_ProtectionTest__myPrivate'] = 3
print pt.getMyPrivate() , '\n'

print "trying to change the function (success: 4): "
def setMyPrivate(self, myPrivate):
    self.__dict__['_ProtectionTest__myPrivate'] = 4
pt.setMyPrivate = setMyPrivate
pt.setMyPrivate(0)
print pt.getMyPrivate(), '\n'

print "trying to change the dict (success: 5): "
pt.__dict__ = {}
pt.__dict__.__setitem__('_ProtectionTest__myPrivate',5)
print pt.getMyPrivate(), '\n'

print "Still working (correct output = -input = -100): "    
pt.setMyPrivate(100)
print pt.getMyPrivate()  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你是暖光i 2025-01-10 06:46:20

我觉得提出这个问题有一些深刻的困惑。私有变量并不能阻止邪恶的“黑客”。它们与安全无关。他们的目的是促进良好的编程实践,例如保持低耦合

如果“邪恶的程序员”可以访问您的源代码,他或她就可以用它做任何他或她想做的事。将变量称为“私有”不会改变这一点。如果邪恶的程序员试图破坏在另一个系统上执行的程序...将变量称为“私有”对您没有任何好处。它不会改变程序在内存中存储和操作的方式。它只是强制执行(在我看来,以一种不必要的复杂方式)关注点分离

另外,值得注意的是,在正常情况下,您不必经历所有这些恶作剧......

MyClass.__dict__ = {}
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not')

分配给受保护的变量。您甚至不必覆盖 __dict__。你可以这样做:

MyClass._MyClass__protectedVariable = '...but it is not'

因为事实并非如此。我的意思是,受到保护。名称修改的主要目的是防止命名空间冲突。如果您只想要一个“私有”属性,只需在其前面加上一个下划线即可。期望你的用户尊重惯例,并期望你的滥用者无论你做什么都会打破惯例。

I feel that there is some deep confusion motivating this question. Private variables aren't there to keep the evil "hackers" away. They have nothing to do with security. They're there to promote good programming practices like maintaining low coupling.

If an "evil programmer" has access to your source code, he or she can do whatever he or she wants to with it. Calling a variable "private" won't change that. If said evil programmer is trying to compromise your program executing on another system... calling a variable "private" will do you no good. It doesn't change anything about the way the program is stored and manipulated in memory. It just enforces (in an unnecessarily complex way IMO) separation of concerns.

Also, it's worth noting that under normal circumstances you don't have to go through all these shenanigans...

MyClass.__dict__ = {}
MyClass.__dict__.__setitem__('_MyClass__protectedVariable','...but it is not')

...to assign to a protected var. You don't even have to overwrite __dict__. You can just do this:

MyClass._MyClass__protectedVariable = '...but it is not'

Cause it's really not. Protected, I mean. The main purpose of name mangling is to prevent namespace collisions. If you just want a "private" attribute, simply prefix it with a single underscore. Expect your users to respect convention, and expect your abusers to break it no matter what you do.

昔梦 2025-01-10 06:46:20

在 Python 中,您不能以这种方式“保护”属性。为什么你与来电者处于敌对关系?你和他需要在一些事情上达成一致,这就是其中之一。写出更好的文档,与他成为更好的朋友。我不知道你真正的问题是什么,但它无法用代码解决。

其他语言(例如 Java 和 C++)提供了 private 等的分离,但 Python 根本没有。事后你无法将其固定。

如果您告诉我们更多有关这个邪恶程序员是谁的信息,以及为什么您和他在如何使用您的代码方面存在分歧,我们也许可以为您提供其他解决方案的想法。

In Python, you cannot "protect" attributes this way. Why are you in an antagonistic relationship with your caller? You and he need to agree on some things, this is one of them. Write better docs, become better friends with him. I don't know what your real problem is, but it cannot be solved with code.

Other languages like Java and C++ offer separation with private and so on, but Python simply does not. You cannot bolt it on after the fact.

If you tell us more about who this evil programmer is, and why you and he disagree about how your code should be used, we might be able to give you other ideas for solutions.

人生百味 2025-01-10 06:46:20

AFAIK 在 Python 中确实没有办法做到这一点。无论您做什么,任何人都可以复制您的源代码并删除您的黑客行为,或者(在大多数情况下)从类继承并覆盖它,或者直接重新分配方法。

但是:你为什么这么关心?如果你将其命名为__whatever,那么这是非常明确的文档,如果用户搞乱了它,发生的任何不好的事情都是他们自己的错。

AFAIK there's not really a way to do this in Python. No matter what you do, anyone could always copy your source and remove your hacks, or (in most cases) either inherit from the class and override it or just directly reassign the methods.

But: why do you care so much? If you name it __whatever that's very clear documentation that if users mess with this, anything bad that happens is their own damn fault.

若相惜即相离 2025-01-10 06:46:20

Python 对于这种数据更改并没有很好的保护措施。但这被视为一个功能。也许关于 `final` 关键字等效于 Python 中的变量? 的常量/finals 的不同问题会有所帮助。
回答您的问题:在同一可执行文件中使用外部代码运行的类中,可能没有办法保护数据免受操纵。您很可能需要将数据存储在单独的进程中,并提供某种 api 来与外部进程交换数据。

Python isn't very protective regarding this kind of data alteration. But this is seen to be a feature. Maybe a different question about constants/finals at `final` keyword equivalent for variables in Python? is of some help.
To answer your question: There is probably no way to protect data against manipulation in your class running with foreign code in the same executable. You would most probably need to store your data in a separate process and provide some kind of api to exchange data with the foreign process.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文