开发者社区> 异步社区> 正文

《Java编码指南:编写安全可靠程序的75条建议》—— 指南1:限制敏感数据的生命周期

简介: 内存中的敏感信息很容易受到攻击,导致泄漏。对于以下条件,不管应用程序满足哪一个,能在应用程序所在的系统上执行代码的攻击者,都能访问这些数据。
+关注继续查看

本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.1节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F.Sutherland(迪恩 F.萨瑟兰), David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

指南1:限制敏感数据的生命周期

内存中的敏感信息很容易受到攻击,导致泄漏。对于以下条件,不管应用程序满足哪一个,能在应用程序所在的系统上执行代码的攻击者,都能访问这些数据。

使用对象来存储敏感数据,但是内容在使用后没有被清除或没有被垃圾收集器回收。
具有可以被操作系统按需(例如,为了执行内存管理任务或者为了支持系统休眠)交换到磁盘的内存页面。
在缓冲区(如BufferedReader)中有敏感数据。这些缓冲区持有敏感数据在操作系统缓存或内存中的副本。
使用了一些反射机制来控制敏感数据的流动,这些反射技巧可能规避掉系统对该数据的生命周期限制。
通过调试信息、日志文件、环境变量、线程转储和核心转储等方式暴露敏感数据。
如果内存中包含的敏感数据在使用后没有及时被清除,那么这些数据将极有可能被泄露。为了降低敏感数据泄露的风险,程序必须尽可能地最小化敏感数据的生命周期。

完全缓解(即对内存数据万无一失的保护)需要底层操作系统和Java虚拟机的支持。例如,如果将敏感数据交换至磁盘是一个问题,那么就需要有一个禁用交换和休眠的安全操作系统。

违规代码示例
在以下违规代码示例中,程序从控制台读取用户名和密码信息,并将密码存储在一个String对象中。在垃圾收集器回收这个String对象关联的内存之前,凭证信息会一直处于暴露状态。

class Password {
 public static void main (String args[]) throws IOException {
  Console c = System.console();
  if (c == null) {
   System.err.println("No console.");
   System.exit(1);
  }

  String username = c.readLine("Enter your user name: ");
  String password = c.readLine("Enter your password: ");

  if (!verify(username, password)) {
   throw new SecurityException("Invalid Credentials");
  }

  // ...
 }

 // Dummy verify method, always returns true
 private static final boolean verify(String username, 
   String password) {
  return true;
 }
}```
合规解决方案
下面的合规解决方案使用Console.readPassword()方法从控制台获取密码信息。

class Password {
 public static void main (String args[]) throws IOException {
  Console c = System.console();

  if (c == null) {
   System.err.println("No console.");
   System.exit(1);
  }

  String username = c.readLine("Enter your user name: ");
  char[] password = c.readPassword("Enter your password: ");

  if (!verify(username, password)) {
   throw new SecurityException("Invalid Credentials");
  }

  // Clear the password
  Arrays.fill(password, ' ');
 }

 // Dummy verify method, always returns true
 private static final boolean verify(String username,
   char[] password) {
  return true;
 }
}`
Console.readPassword()方法允许密码以字符序列的形式返回,而不是以String对象的形式。因此,程序员可以在使用密码后立即将其从数组中清除。同时这个方法也禁止将密码输出到控制台。

违规代码示例
下面的违规代码示例使用了一个BufferedReader来包装InputStreamReader对象,导致敏感数据可以从文件中被读取。

void readData() throws IOException{
 BufferedReader br = new BufferedReader(new InputStreamReader(
  new FileInputStream("file")));
 // Read from the file
 String data = br.readLine();
}```
BufferedReader.readLine()方法以String对象的形式返回敏感数据,导致数据在不被需要后仍然会存留很久。BufferedReader.read(char[], int, int)方法可以读取和填充一个char数组,不过,它需要程序员在使用完数组中的敏感数据后,手动将其清除,否则就会导致泄漏。另外,尽管BufferedReader是用来包装FileReader对象的,但它同样也会遭遇相似的陷阱。

合规解决方案
在下面的合规解决方案中,程序使用了一个直接分配的新I/O(new I/O,NIO)缓冲区从文件中读取敏感数据。这些数据可以在使用后被立即清除,并且不会被缓存或缓冲在多个位置上,它只会出现在系统内存中。

void readData(){
 ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
 try (FileChannel rdr =
    (new FileInputStream("file")).getChannel()) {
  while (rdr.read(buffer) > 0) {
   // Do something with the buffer
   buffer.clear();
  }
 } catch (Throwable e) {
  // Handle error
 }
}`
注意,必须手动清除缓冲数据,因为垃圾收集器不会回收直接缓冲区。

适用性
对敏感数据生命周期限制失败,导致信息泄露。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java线程的生命周期(转)
Java线程的生命周期   一个线程的产生是从我们调用了start方法开始进入Runnable状态,即可以被调度运行状态,并没有真正开始运行,调度器可以将CPU分配给它,使线程进入Running状态,真正运行其中的程序代码。
857 0
将jQuery Pagination分页插件用于不使用AJAX加载数据的页面
将jQuery Pagination分页插件用于不使用AJAX加载数据的页面,项目使用SpringMVC,使用Freemarker绑定数据,但分页显示样式不想自己处理,所以使用jQuery Pagination分页插件。
760 0
[20121114]Oracle数据文件大小限制.txt
[20121114]Oracle数据文件大小限制.txtSQL> show parameter db_block_sizeNAME           TYPE        VALUE-------------- ----------- ------db_bl...
606 0
java安全编码指南之:声明和初始化
java安全编码指南之:声明和初始化
9 0
java安全编码指南之:Number操作
java安全编码指南之:Number操作
10 0
java安全编码指南之:Mutability可变性
java安全编码指南之:Mutability可变性
13 0
java安全编码指南之:输入校验
java安全编码指南之:输入校验
13 0
java安全编码指南之:字符串和编码
java安全编码指南之:字符串和编码
13 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载