Java 文件名空字节截断漏洞

    2013年9月10日发布的修复了空字节截断这个历史遗留问题。此次更新在java.io.File类中添加了一个isInvalid方法,专门检测文件名中是否包含了空字节。

    修复的JDK版本所有跟文件名相关的操作都调用了isInvalid方法检测,防止文件名空字节截断。

    修复前(Java SE 7 Update 25)和修复后(Java SE 7 Update 40)的对比会发现Java SE 7 Update 25中的java.io.File类中并未添加\u0000的检测。

    受空字节截断影响的JDK版本范围:JDK<1.7.40,单是JDK7于2011年07月28日发布至2013年09月10日发表Java SE 7 Update 40这两年多期间受影响的就有16个版本,值得注意的是JDK1.6虽然JDK7修复之后发布了数十个版本,但是并没有任何一个版本修复过这个问题,而JDK8发布时间在JDK7修复以后所以并不受此漏洞影响。

    参考:

    1. JDK-8014846 : File and other classes in java.io do not handle embedded nulls properly
    2. Oracle Java 历史版本下载

    测试类FileNullBytes.java:

    1. package com.anbai.sec.filesystem;
    2. import java.io.IOException;
    3. /**
    4. * @author yz
    5. */
    6. public class FileNullBytes {
    7. public static void main(String[] args) {
    8. String fileName = "/tmp/null-bytes.txt\u0000.jpg";
    9. FileOutputStream fos = new FileOutputStream(new File(fileName));
    10. fos.write("Test".getBytes());
    11. fos.flush();
    12. fos.close();
    13. e.printStackTrace();
    14. }
    15. }
    16. }

    使用JDK1.7.0.25测试成功截断文件名:

    使用JDK1.7.0.80测试写文件截断时抛出java.io.FileNotFoundException: Invalid file path异常:

    -w1017

    Java空字节截断利用场景最常见的利用场景就是文件上传时后端获取文件名后使用了endWith、正则使用如:.(jpg|png|gif)$验证文件名后缀合法性且文件名最终原样保存,同理文件删除(delete)、获取文件路径(getCanonicalPath)、创建文件(createNewFile)、文件重命名()等方法也可适用。

    最简单直接的方式就是升级JDK,如果担心升级JDK出现兼容性问题可在文件操作时检测下文件名中是否包含空字节,如JDK的修复方式:fileName.indexOf('\u0000')即可。