From e26507821087bf26cb6a4f3dcf0d754a7eaf04ee Mon Sep 17 00:00:00 2001
From: Thomas <tschneider.ac@gmail.com>
Date: Tue, 27 Dec 2022 18:00:24 +0100
Subject: [PATCH] Secure zip

---
 .../app/fedilab/android/helper/ZipHelper.java | 30 +++++++++++++++----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/app/src/main/java/app/fedilab/android/helper/ZipHelper.java b/app/src/main/java/app/fedilab/android/helper/ZipHelper.java
index e9873b94..ffe595d8 100644
--- a/app/src/main/java/app/fedilab/android/helper/ZipHelper.java
+++ b/app/src/main/java/app/fedilab/android/helper/ZipHelper.java
@@ -136,14 +136,22 @@ public class ZipHelper {
                     f.mkdirs();
                 }
                 boolean successful = true;
-                try (ZipInputStream zin = new ZipInputStream(new FileInputStream(fullPath + ".zip"))) {
+                FileInputStream fileInputStream = new FileInputStream(fullPath + ".zip");
+                try (ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fileInputStream))) {
                     ZipEntry ze;
                     while ((ze = zin.getNextEntry()) != null) {
                         if (!successful) {
                             break;
                         }
-                        String path = fullPath + ze.getName();
-                        File unzipFile = new File(path);
+                        File unzipFile = new File(fullPath, ze.getName());
+                        boolean sure = ensureZipPathSafety(unzipFile, fullPath);
+                        if (!sure) {
+                            Handler mainHandler = new Handler(Looper.getMainLooper());
+                            Runnable myRunnable = () -> Toasty.error(context, context.getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
+                            mainHandler.post(myRunnable);
+
+                            return;
+                        }
                         FileOutputStream out = new FileOutputStream(unzipFile, false);
                         BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
                         try {
@@ -157,9 +165,9 @@ public class ZipHelper {
                             fout.close();
                         }
                         if (ze.getName().contains("settings")) {
-                            successful = restoreSettings(context, Uri.fromFile(new File(path)));
+                            successful = restoreSettings(context, Uri.fromFile(new File(unzipFile.getAbsolutePath())));
                         } else if (ze.getName().contains("database")) {
-                            successful = importDB(context, path);
+                            successful = importDB(context, unzipFile.getAbsolutePath());
                         } else {
                             break;
                         }
@@ -183,6 +191,18 @@ public class ZipHelper {
 
     }
 
+    private static boolean ensureZipPathSafety(final File outputFile, final String destDirectory) {
+        String destDirCanonicalPath;
+        try {
+            destDirCanonicalPath = (new File(destDirectory)).getCanonicalPath();
+            String outputFilecanonicalPath = outputFile.getCanonicalPath();
+            return outputFilecanonicalPath.startsWith(destDirCanonicalPath);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
     private static String storeSettings(Context context, String suffix) {
         boolean res = false;
         ObjectOutputStream output = null;