网上说密码要用 char[]而不是 String 储存的原因是:
这个黑客是如何利用所谓的“进程内存转储”偷密码啊? 感觉不可思议啊
1
nevin47 2017-06-24 19:02:43 +08:00 via Android
看这意思是趁 GC 之前构造一个场景把进程 core 掉,然后 dump 文件里面去找明文密码?不过感觉没啥软用啊,难道是去套软件内私钥的?这时代谁不把私钥先加个密啊
|
2
wevsty 2017-06-24 19:45:04 +08:00 1
string 的本质是帮你在堆上创建了空间储存字符串的,string 自己析构的时候是把空间还给了内存分配器,但是可能没有对空间填充内容(这取决于 string 的实现),并且内存分配器也可能没有对这些空间做任何操作,所以析构以后 dump 内存仍然有可能找到密码。
你用 malloc 分配或者在栈上的数组也会有一样的问题这取决于有关的实现本身。 关键问题不在于你用的到底是什么,而是使用完成后对于需要保密的数据应该手动覆盖填充有关的空间。 |
3
ech0x 2017-06-24 20:04:19 +08:00 via iPad
@wevsty 请教一下,java char[] 的实现不是直接分配一块固定的内存的吗?如果是的话,用 char[] 不是照样可以被获取嘛。
|
4
geelaw 2017-06-24 20:09:23 +08:00
|
5
ech0x 2017-06-24 20:15:14 +08:00 via iPad
@geelaw 谢谢了解了。 这么看来这个攻击方式几乎是无解了的嘛。对方只要能获取你的进程基本上就可以被攻击。如果像 c 用指针数组,密码被分散在内存的各处,能不能防范这个攻击呢?
|
7
nevin47 2017-06-24 20:21:42 +08:00 via Android
@geelaw 私钥可以拆分后再做二次加密,虽然理论可以继续追着去破译,但是这种破译成本已经成指数扩大了
|
8
geelaw 2017-06-24 20:31:15 +08:00 via iPhone
@nevin47 你的想法有很多值得二次思考的地方……比如为什么再次加密后破解难度指数增加?用于二次加密的密码存放在哪里?如果也在进程内存,只要读出二次加密的密码再解密私钥密文不就行了?
|
10
wevsty 2017-06-24 20:57:51 +08:00 1
@ech0x
推荐使用 char[]我觉得是一种偏见。 大概会有人认为使用 char[]的话在不再需要密钥之后手动填充这段内存空间会比较方便,覆盖了原本密钥的内容那么就不用担心在这个时刻之后会被人内存 dump 了。 但是实际上,string 和 char[]没有什么不同的地方,可以在析构之前手动填充一下每个元素,甚至可以继承一个自己的 string 然后在析构函数里面强制填充。 |
11
geelaw 2017-06-24 21:09:53 +08:00
@wevsty String 是不可变,且 String 是 final,因此这条路走不通。
而且一个程序不可以依赖 finaliser 来做清理,因为在内存足够的硬件上,GC 可以选择永远不回收内存。 |
12
billlee 2017-06-24 21:17:59 +08:00
这和 coredump 有什么关系,如果黑客能读取到 coredump, 也就能直接读你的进程内存,或者给你的进程上调试器。
|
13
binux 2017-06-24 21:21:18 +08:00
如果黑客能接触到你的内存,他干点别的什么不好?
|
14
wevsty 2017-06-24 21:26:44 +08:00
@geelaw
您说得是 JAVA 么?这方面我不太清楚。 从 C++的角度上,string 是可以被继承的,当一个对象的生命周期结束的时候,析构函数必然会被调用。当然重点不在这里,而在于不再需要密钥的时候密钥是否被正确销毁,不管会不会回收内存,只要用完了正确的覆盖掉原始数据就可以了。 |
15
owt5008137 2017-06-24 21:30:33 +08:00 via Android
啥语言? c 艹的话 char[]被删除了也不一定回立刻被回收
|
16
sinxccc 2017-06-24 21:33:26 +08:00 2
从安全的角度,能被对方物理接触到和远程登录进去的系统是毫无安全性可言的,一旦到那个地步,唯一能做的就是自毁关键数据和销毁相关的密钥,证书等等。在这个情况下还在比较 char [] 和 string 的安全性就好像关心一个重病垂死的人吃东西太少会不会对胃不好一样。
但总有一些例外比如之前的 heartbleed 漏洞,还有一个常见的情况就是从机器上传递出来的 coredump 文件,这些可能会带出一部分内存的情况。针对这种一般是用加密一部分堆的方式来解决,愿意了解细节的话可以搜搜 Akamai secure heap 和 heartbleed 的故事,很是一波三折。 |
17
gamexg 2017-06-24 21:44:57 +08:00
看到后面才知道说的时 java,已开始以为时 c,c 无所谓,强制转换然后置 0 即可。
java 不熟悉,看起来没有 SecureString,如果考虑到这个的话的确需要用 char[] 。 |
19
guyeuro OP |
20
lrxiao 2017-06-24 22:06:55 +08:00
看 SERT C++指导有一条注意跨越可信边界时候注意 padding bits,感觉和这个案例差不多
|
21
nevin47 2017-06-24 22:29:28 +08:00 via Android
|
23
lcdtyph 2017-06-24 23:23:30 +08:00 via iPhone
|
24
xenme 2017-06-24 23:44:37 +08:00 via iPhone
默认情况下不管是 char[]还是 string 在内存中对于你要这种短小的内容来说基本都是连续分布,没有特别保护。。
所以攻击的时候很容易通过遍历内存来攻击,也就是直接 dump 后扫一遍可能就扫出来了。。 而一般的处理是对于这些敏感的内容使用流式处理,使用过程中经过处理,使用后立即清理来尽可能的减少明文存在的时间。 但是你只要输入或者输出需要使用到明文,那么必然会有一个时刻可以看到明文,如果此时 dump 出来,那么依然可以被攻击。 |
25
mengskysama 2017-06-25 01:21:23 +08:00
@guyeuro 黑客既然能 dump 内存基本上应该就是有很高的权限了,有些工具更甚,密码常驻内存
感兴趣可以看看这个 https://github.com/huntergregal/mimipenguin |