gpt4 book ai didi

java - 使用 System.console() 读取密码

转载 作者:搜寻专家 更新时间:2023-11-01 01:00:47 24 4
gpt4 key购买 nike

java.io.Console 的 javadoc 中有一个安全说明类:

Security note: If an application needs to read a password or other secure data, it should use readPassword() or readPassword(String, Object...) and manually zero the returned character array after processing to minimize the lifetime of sensitive data in memory.

 Console cons;
char[] passwd;
if ((cons = System.console()) != null &&
(passwd = cons.readPassword("[%s]", "Password:")) != null) {
...
java.util.Arrays.fill(passwd, ' ');
}

我不明白为什么要采取如此严厉的措施?当读取密码的方法从堆栈弹出时,passwd 局部变量引用的数组对象将符合垃圾回收条件。没有人(即使是攻击者)可以获取对该数组的引用,假设该数组没有逃脱方法范围。

那么为什么你需要修改数组(删除密码),当你知道一旦方法从堆栈中弹出它就会有资格进行 GC?他们说:

to minimize the lifetime of sensitive data in memory

但对我来说,这种编程风格似乎相当......绝望。

最佳答案

仅仅因为对象符合垃圾回收条件并不意味着它会立即被垃圾回收。在实际执行垃圾回收之前的那段时间里,攻击者可能会获得堆内存转储,例如他们可以从中检索密码。

通过将其归零,机会窗口被最小化。

编辑:实际实验:

创建以下 Java 程序:

public class Main {
private static void readPassword() {
char[] password = System.console().readPassword();
}

public static void main(String[] args) throws Exception {
readPassword();
Thread.sleep(1000 * 3600);
}
}
  1. javac Main.java
  2. java 主程序
  3. 输入密码(例如topsecret),回车

接下来打开另一个终端,找出进程的 PID(假设它是 1000)并使用 jmap 创建堆转储:

jmap -dump:format=b,file=dump.bin 1000

安装并打开 VisualVM探查器,转到 File/Load 并选择您刚刚创建的堆转储。

接下来转到 OQL 控制台并运行以下查询:

select a from char[] a where a.length == 9 && a[0] == 't'

如您在所附屏幕截图中所见,找到了包含“topsecret”的数组,即使在进行堆转储时没有对该数组的可访问引用。因此,这证明即使对象在本地被引用,它们也会保留在堆上,直到被垃圾回收。

VisualVM

现在,如果我将数组清零并再次尝试整个过程,将找不到包含密码的数组。

关于java - 使用 System.console() 读取密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27661946/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com