【发布时间】:2013-05-22 13:09:18
【问题描述】:
我在一个类中有一个方法可以解密一个变量并返回它。使用后我用“del”删除返回的变量。
访问这些垃圾值有什么危险......我怎样才能最好地保护自己免受它们的伤害?
代码如下:
import decrypter
import gc
# mangled variable names used
def decrypt(__var):
__cleartext = decrypter.removeencryption(__var)
return __cleartext
__p_var = "<512 encrypted password text>"
__p_cleartext = decrypt(__p_var)
<....do login with __p_cleartext...>
del __p_var, __p_cleartext
gc.collect()
此时是否可以利用任何变量,包括 __var 和 __cleartext?
谢谢!
我做了更多的谷歌搜索。在我花几个小时走错路之前……我听到的是:
- 将密码作为盐渍散列存储在系统上(它现在正在这样做)。
- 用户应在套件启动时输入哈希的盐(现在已完成)
- 但是,盐应该保存在 C 进程而不是 python 中。
- python 脚本应将哈希传递给 C 进程进行解密。
python脚本正在处理mysql数据库的登录,打开数据库连接需要密码。
如果代码是...
# MySQLdb.connect(host, user, password, database)
mysql_host = 'localhost'
mysql_db = 'myFunDatabase'
hashed_user = '\xghjd\xhjiw\xhjiw\x783\xjkgd6\xcdw8'
hashed_password = 'ghjkde\xhu78\x8y9tyk\x89g\x5de56x\xhyu8'
db = MySQLdb.connect(mysql_host, <call_c(hashed_user)>, <call_c(hashed_password)>, mysql_db])
这会(至少)解决python留下垃圾的问题吗?
附:我还发现了关于 memset (Mark data as sensitive in python) 的帖子,但我假设如果我使用 C 来解密哈希,这没有帮助。
附言dycrypter 目前是一个 python 脚本。如果我将 memset 添加到脚本中,然后使用 py2exe 或 pyinstaller “编译”它……这实际上有助于保护密码吗?我的直觉说不,因为 pyinstaller 所做的只是将普通解释器和本地解释器创建的相同字节码打包......但我对此知之甚少......?
所以...按照 Aya 建议在 C 中制作加密模块,以下设置会留下多少可识别的内存占用。部分大问题是;解密密码的能力必须在整个程序运行期间保持可用,因为它将被重复调用......这不是一次性的事情。
创建一个在用户登录时启动的 C 对象。它包含解密例程和保存用户在登录时输入的盐的副本。存储的盐在运行对象(在内存中)中被隐藏,因为它自己的加密例程使用随机生成的盐进行了散列。
随机生成的盐仍然必须保存在对象的变量中。这并不是为了保护盐,而只是为了尝试混淆内存足迹,如果有人应该偷看它(使盐难以识别)。 IE。 c-obj
mlock() /*to keep the code memory resident (no swap)*/
char encrypt(data, salt){
(...)
return encrypted_data
}
char decrypt(data, salt){
(...)
return decrypted_data
}
stream_callback(stream_data){
return decrypt(stream_data, decrypt(s-gdhen, jhgtdyuwj))
}
void main{
char jhgtdyuwj=rand();
s-gdhen = encrypt(<raw_user_input>, jhgtdyuwj);
}
然后,python 脚本直接调用 C 对象,它将未加密的结果直接传递给 MySQLdb 调用,而不将任何返回值存储在任何变量中。即
#!/usr/bin/python
encrypted_username = 'feh9876\xhu378\x&457(oy\x'
encrypted_password = 'dee\x\xhuie\xhjfirihy\x^\xhjfkekl'
# MySQLdb.connect(host, username, password, database)
db = MySQLdb.connect(self.mysql_host,
c-obj.stream_callabck(encrypted_username),
c-obj.stream_callback(encrypted_password),
self.mysql_database)
这会留下什么样的内存占用,可以窥探?
【问题讨论】:
-
值得注意的是,删除名称并不能保证该对象将被删除 - 它的其他名称可能仍然存在。
-
如果您担心未经授权访问明文密码,可能有很多方法可以在它被 gc'd 后访问它。如果你特别偏执,你可能想在 C 中做这部分,然后用随机数据覆盖 RAM。
-
关于您的编辑:即使您在 C 中实现了整个过程,并在完成后将进程地址空间归零,也不能保证操作系统没有分页出地址空间部分其中包含明文密码,因此它可能会在磁盘上保留很长时间。而且即使你禁用了虚拟内存,如果有人可以访问进程的内存空间,也总会有一些机会抢到明文密码。 TBH,我不会担心 - 如果密码只是 MySQL 的,有更简单的方法可以绕过它的安全性。
-
您是否特别担心密码安全问题?随机人是否有可能访问运行此 Python 代码的系统?
-
@aya:我最担心的是;如果用户获得对系统的访问权限(甚至是 root)......文件中没有任何内容可以帮助他们。我什至不认为你使用的 MySQLdb 漏洞会起作用,因为脚本不会在没有 salt 的情况下传递登录凭据……必须在脚本启动时传入。但是,盐将存在于内存中的变量中。据我所知,获取此变量的唯一方法是嗅出或转储内存(或检查交换文件......但在 C 中使用 memlock 应该可以防止它被交换)。所以,这就是我想要保护的。
标签: python security exploit garbage