From 087f89ebc0dd87e74c8945f074f25b51b195cb83 Mon Sep 17 00:00:00 2001
From: Connor Tumbleson <iBotPeaches@users.noreply.github.com>
Date: Tue, 2 Jan 2024 06:11:03 -0500
Forwarded: https://github.com/iBotPeaches/Apktool/commit/087f89ebc0dd87e74c8945f074f25b51b195cb83
Subject: [PATCH 1/1] Prevent arbitrary file writes with malicious resource
 names. (#3484)

CVE-2024-21633

* refactor: rename sanitize function

* fix: expose getDir

* fix: safe handling of untrusted resource names

 - fixes: GHSA-2hqv-2xv4-5h5w

* test: sample file for GHSA-2hqv-2xv4-5h5w

* refactor: avoid detection of absolute files for resource check

* chore: enable info mode on gradle

* test: skip test on windows

* chore: debug windows handling

* fix: normalize entry with file separators

* fix: normalize filepath after cleansing

* chore: Android paths are not OS specific

* refactor: use java.nio for path traversal checking

* chore: align path separator on Windows for Zip files

* chore: rework towards basic directory traversal

* chore: remove '--info' on build.yml
---
 .../java/brut/androlib/res/decoder/ResFileDecoder.java    | 8 ++++++++
 brut.j.util/src/main/java/brut/util/BrutIO.java           | 7 +++++++
 2 files changed, 15 insertions(+)

diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java
index a3174411..16ad35f9 100644
--- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java
+++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java
@@ -25,6 +25,7 @@ import brut.androlib.res.data.value.ResFileValue;
 import brut.directory.DirUtil;
 import brut.directory.Directory;
 import brut.directory.DirectoryException;
+import brut.util.BrutIO;
 
 import java.io.*;
 import java.util.Map;
@@ -47,6 +48,13 @@ public class ResFileDecoder {
         String outResName = res.getFilePath();
         String typeName = res.getResSpec().getType().getName();
 
+        if (BrutIO.detectPossibleDirectoryTraversal(outResName)) {
+            outResName = inFileName;
+            LOGGER.warning(String.format(
+                "Potentially malicious file path: %s, using instead %s", res.getFilePath(), outResName
+            ));
+        }
+
         String ext = null;
         String outFileName;
         int extPos = inFileName.lastIndexOf(".");
diff --git a/brut.j.util/src/main/java/brut/util/BrutIO.java b/brut.j.util/src/main/java/brut/util/BrutIO.java
index 76432638..f99144e0 100644
--- a/brut.j.util/src/main/java/brut/util/BrutIO.java
+++ b/brut.j.util/src/main/java/brut/util/BrutIO.java
@@ -94,6 +94,13 @@ public class BrutIO {
         return canonicalEntryPath.substring(canonicalDirPath.length());
     }
 
+    public static boolean detectPossibleDirectoryTraversal(String entry) {
+        if (OSDetection.isWindows()) {
+            return entry.contains("..\\") || entry.contains("\\..");
+        }
+        return entry.contains("../") || entry.contains("/..");
+    }
+
     public static String normalizePath(String path) {
         char separator = File.separatorChar;
 
-- 
2.39.2

