当前位置:编程学习 > JAVA >>

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 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,