解压功能验证正常,zip炸弹防御部分还没验证完,后续验证后再确认
private static final int MAX_COUNT = 10000; // 注意,long类型后面要加L private static final long MAX_SIZE = 4L * 1024 * 1024 * 1024; private static final int PATH_LENGTH = 512; /** * zip解压及zip炸弹的防御 * 防御要点:1.校验解压后文件大小 2.校验解压后的条目总数 3.解压时防止跨目录攻击 * 4.校验解压文件路径 5.校验文件路径长度 * @param zipFilePath */ public static void unzip(String zipFilePath) throws Exception { InputStream inputStream = null; FileOutputStream fileOutputStream = null; // 判断是否zip文件 if (!isZipFile(zipFilePath)) { return; } // 创建解压文件存放目录 File file = new File("D:\\unzip"); if (!file.exists()) { file.mkdirs(); } // 使用ZipFile获得解压文件对象,第二个参数是编码 ZipFile zipFile = new ZipFile(zipFilePath, Charset.forName("GBK")); // 用Enumeration接收压缩文件中的每一个条目(目录或文件) Enumeration<? extends ZipEntry> zipEntries = zipFile.entries(); // 统计条目数量 int count = 0; // 统计解压文件大小 long size = 0L; // 遍历zipEntries while (zipEntries.hasMoreElements()) { // 校验zip解压条目总数 if (++count > MAX_COUNT) { //TODO delete unzip files return; } // 获得压缩文件中此次的条目 ZipEntry zipEntry = zipEntries.nextElement(); size += zipEntry.getSize(); // 校验解压后的文件大小 if (size > MAX_SIZE) { // TODO delete unzip files return; } // 获取此条目(文件或目录)的路径 String path = "D:\\unzip\\" + zipEntry.getName(); // 校验文件路径长度 if (path.length() > PATH_LENGTH) { // TODO delete unzip file return; } // 判断解压文件路径是否合法 if (!isLegalPath(path)) { // TODO delete unzip files return; } // 是目录则创建文件夹,是文件则用流读写出来 LOG.info("判断是文件夹还是文件"); if (zipEntry.isDirectory()) { LOG.info("是文件夹"); new File(path).mkdirs(); } else { try { LOG.info("开始用流读写文件"); inputStream = zipFile.getInputStream(zipEntry); fileOutputStream = new FileOutputStream(path); byte[] data = new byte[8 * 1024]; int num = -1; while ((num = inputStream.read(data)) != -1) { fileOutputStream.write(data, 0, num); } } finally { if (fileOutputStream != null) { fileOutputStream.close(); } if (inputStream != null) { inputStream.close(); } } } } } /** * 判断是否是zip文件 * @param zipFilePath * @return */ private static boolean isZipFile(String zipFilePath) { if (zipFilePath == null) { return false; } File file = new File(zipFilePath); if (file.exists() && file.getName().endsWith("zip")) { return true; } return false; } /** * 判断解压文件路径是否合法 * @param path * @return */ private static boolean isLegalPath(String path) throws Exception { if (path == null) { return false; } if (new File(path).getCanonicalPath().startsWith("D:\\unzip\\")) { return true; } return false; }
修正后删除本句话
原文地址:https://www.cnblogs.com/hello4world/p/12227391.html
时间: 2024-11-05 21:49:57