我正在讨论如何保护存储在Java程序中的敏感信息(例如密码).根据安全要求,清除包含敏感信息的存储器,例如通过将字节值设置为全零.担心的是攻击者可以观察与应用程序进程相关的内存,因此我们希望尽可能多地限制此类敏感信息的时间窗口.以前,项目涉及C++,所以memset()就足够了.
(顺便说一下,memset()的使用已经引起了质疑,因为已知一些编译器会根据以下假设来优化它的使用:由于以后不使用内存,所以不需要将其归零.第一个地方.对于那些谷歌用于"memset"和"清晰记忆"等的人来说,这是一个免责声明.
现在,我们手中有一个Java项目被迫遵守这个要求.
对于Java对象,我的理解是:
对于原始人,我的理解是:
我的同事声称Java原语是不可变的,并且NSA和Oracle都提供了有关此要求缺乏Java支持的文档.
我的立场是,原语可以(至少在某些情况下)通过将值设置为零(或布尔值为false)来归零,并且以这种方式清除内存.
我正在尝试验证JLS或其他"官方"文档中是否存在关于JVM在基元内存管理方面所需行为的语言.我能找到的最接近的是Oracle网站上的"Java编程语言的安全编码指南",其中提到了在使用后清除字符串数组.
当我的同事称原语不可变时,我会对定义进行狡辩,但我很确定他的意思是"记忆不能被适当归零" - 让我们不要担心.我们没有讨论他是否意味着最终变量 - 从我们正在谈论的背景来看.
对此有任何确定的答案或参考?我很感激任何可以告诉我错在哪里或确认我是对的.
编辑:经过进一步的讨论,我已经能够澄清我的同事正在考虑原始包装,而不是原始本身.因此,我们留下了如何安全地清除内存的原始问题,最好是对象.此外,澄清一下,敏感信息不仅仅是密码,还包括IP地址或加密密钥等.
是否有任何商业JVM提供某些对象的优先级处理功能?(我想这实际上会违反Java规范,但我想我会问,以防万一我错了.)
我们知道优先选择char []而不是java.lang.String来存储密码.这是出于以下两个原因(正如我所读):
但是java.sql.DriverManager没有符合上述最佳实践的getConnection(),因为它的password参数是String.
DriverManager.getConnection(String url,String user,String password)
我认为API应该有一个带有以下签名的重载方法:
DriverManager.getConnection(String url,String user,char [] password)
你怎么看待这件事?你有没有看到任何替代方法来克服这种退缩?
很想听听你的想法.
这是关于Java字符串常量池.在我的一个程序中,我正在解密数据库的密码并将其存储在字符串中.我听说Java Strings将存储在一个常量池中,它们不会被VM重新启动或加载String Quits的ClassLoader破坏.
如果是这种情况,我的密码将存储在字符串池中.我非常关心这个问题.有没有其他方法来摧毁这些文字或我能做的任何其他事情.
请在此建议,
此致,Sunny.
我需要将数据从我的iPhone应用程序发送到我的网络服务器,然后再返回.为了安全地做到这一点,我正在使用加密算法.它需要服务器和用户必须知道的密钥才能进行解密.我正在考虑在我的应用程序和服务器上使用一个简单的静态字符串作为键,但后来我记得编译后的代码仍然可以被反汇编和查看,但只是在一定程度上.
那么,通过在我的应用程序的源代码中放置加密方法和"秘密"字符串,我会有多安全?有没有其他方法可以安全地完成应用程序和服务器之间的通信?
谢谢.
在学习Java时,我了解到Strings 对于存储密码是不安全的,因为你无法手动清除与它们相关的内存(你不能确定它们最终会被gc'ed,内部字符串可能永远不会,甚至之后gc你不能确定物理内存内容真的被擦除了).相反,我使用char数组,所以我可以在使用后将它们清零.我试图在其他语言和平台上搜索类似的做法,但到目前为止我找不到相关的信息(通常我看到的是密码存储在字符串中的代码示例,没有提到任何安全问题).
我对浏览器的情况特别感兴趣.我经常使用jQuery,而我通常的做法就是将密码字段的值设置为空字符串而忘记它:
$(myPasswordField).val("");
Run Code Online (Sandbox Code Playgroud)
但我并不是100%确信它已经足够了.我也不知道用于中间访问的字符串是否安全(例如,当我$.ajax用来将密码发送到服务器时).至于其他语言,通常我没有提到这个问题(我特别感兴趣的另一种语言是Python).
我知道试图建立列表的问题是有争议的,但由于这涉及一个很大程度上被忽视的共同安全问题,恕我直言,这是值得的.如果我弄错了,我会很高兴知道从JavaScript(在浏览器中)和Python.我也不确定是在这里,在security.SE还是在程序员.SE,但由于它涉及安全执行任务的实际代码(不是概念性问题),我相信这个网站是最好的选择.
注意:在低级语言或明确支持字符作为原始类型的语言中,答案应该是显而易见的(编辑:不是很明显,正如@Gabe在下面的答案中所示).我要求那些"一切都是对象"或类似的高级语言,以及那些在幕后执行自动字符串实习的人(所以你可能会创建一个安全漏洞而不会意识到它,即使你'合理谨慎).
更新:根据相关问题的答案,即使char[]在Java中使用也不能保证是防弹的(或者就此而言是.NET SecureString),因为gc可能会移动数组,因此其内容可能会粘在内存中,即使在清除(SecureString至少保留在相同的RAM地址中,保证清除,但其消费者/生产者可能仍然留下痕迹).
我猜@NiklasB.是正确的,即使漏洞存在,漏洞利用的可能性很低,防止漏洞的难度很高,这可能是这个问题大多被忽视的原因.我希望我至少可以找到关于浏览器这个问题的一些参考,但谷歌搜索到目前为止一直没有结果(这个场景至少有一个名字吗?).
我是一名软件工程师,正在构建一个将由政府机构使用的 Android 应用程序。
我们合同中的一项要求是应用程序必须符合 FIPS 140。 https://en.wikipedia.org/wiki/FIPS_140
为了符合 FIPS,我们的应用程序必须在 android 应用程序关闭时将 RAM 中的所有密码对象归零并清除。(通过从 RAM 中清零和清除密码,我们减少了攻击者的机会窗口。即这减轻了冷启动攻击风险:https : //en.wikipedia.org/wiki/Cold_boot_attack)
为了满足这一要求,我们最初遵循以下两个 SO 帖子中的建议将用户密码捕获为 CharArray 而不是字符串
//First collect the password from Edit Text as a []char
int pl = passwordEditText.length();
char[] password = new char[pl];
passwordEditText.getText().getChars(0, pl, password, 0);
//Now set the password on viewmodel
viewModel.setPassword(password)
Run Code Online (Sandbox Code Playgroud)
获得密码后,我们使用它来调用第 3 方网络服务库,该库获取数据以显示在屏幕上。
视图模型伪代码:
public DataObject getData(char[] password){
return this.webService.getData(password);
}
Run Code Online (Sandbox Code Playgroud)
当用户完成我们的应用程序时,我们调用以下方法将密码归零和清除
视图模型伪代码:
public zeroPassword(){
Arrays.fill(this.password, 0);
this.password = null; …Run Code Online (Sandbox Code Playgroud) security ×4
java ×3
string ×3
memory ×2
passwords ×2
android ×1
char ×1
cocoa-touch ×1
constants ×1
disassembly ×1
encryption ×1
objective-c ×1
pool ×1