Java中的 createTempFile()函数 文件名可预测问题
大风起兮云飞扬
前天刚写了篇不可预测性与安全的文章,今天又看到一个案例。
http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/
详细分析可以看上面这个链接,我简单摘要如下:
java.io.File.createTempFile(deploymentName, extension);
这个函数,第一个参数是 前缀, 第二个参数是后缀。它的作用是生成一个临时文件名,比如 prefixrandomNumber.extension
如果prefix和 extenstion 超长都会被截断。
比如如果设置 prefix 是 "temp" , 设置 extenstion 是 ".tmp"
那么 通过 createTempFile 这个函数可能会生成一个 /tmp/temp13245.tmp 这样一个临时文件
(在windows中,是生成于当前用户的temp目录下)
安全隐患在于,在java中,
1. 生成的这个 randomNumber 是在一个不大的范围内,
2. 而且是顺序增长的!作者反编译了java关于这部分的代码,如下:
private static File generateFile(String s, String s1, File file) throws IOException{ if(counter == -1) counter = (new Random()).nextInt() & 0xffff; counter++; return new File(file, (new StringBuilder()).append(s).append(Integer.toString(counter)).append(s1).toString());}public static File createTempFile(String s, String s1, File file) throws IOException{ ... File file1; do file1 = generateFile(s, s2, file); while(!checkAndCreate(file1.getPath(), securitymanager)); return file1;}
在作者的测试环境里,在我的linux测试机器上,我得到了如下结果:
文件比较多,到了文件结束的时候,发现是:
可以看到这个结果非常之具有规律。
在windows上有类似的结果。
值得注意的是,java.util.Random 和系统时间有关,所以非常短的时间内是可能因为时间因子相同而取得同一个随机数的。java.util.Random属于几何分布,而非空间均匀分布。
我的测试代码如下:
import java.io.*;
public class getTemp {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
File f = null;
String extension = ".tmp";
try {
//for (int i=0; i<10; i++){
f = File.createTempFile("temp", extension);
System.out.println(f.getPath());
//}
}
catch (IOException e) {
}
}
}
由于randomNumber的顺序增长,使得这个数字我们完全可以预测,就可能导致一些安全隐患。
之所以说是隐患而不是漏洞,是因为这种底层库里函数的问题都是需要在具体应用里体现的,最后可能导致很严重的问题,也可能永远不会触发这个问题。
Sun Java 6 Update 11已经修复了这个问题
修复的代码反编译如下:
private static File generateFile(String s, String s1, File file) throws IOException{ long l = LazyInitialization.random.nextLong(); if(l == 0x8000000000000000L) l = 0L; else l = Math.abs(l); return new File(file, (new StringBuilder()).append(s).append(Long.toString(l)).append(s1).toString());}
先是扩大了randomNumber的范围,用long型了,其次是不再顺序增长
IBM Java SR3中也修复了这个问题。
最后,生成安全随机数请用:java.security.SecureRandom
补充:软件开发 , Java ,