zip解壓及zip炸彈的防御


解壓功能驗證正常,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;
    }

修正后刪除本句話


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM