diff --git a/jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java b/jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java index b1edeeea3..1c9246c83 100644 --- a/jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java +++ b/jadx-core/src/main/java/jadx/core/utils/files/ZipSecurity.java @@ -1,6 +1,7 @@ package jadx.core.utils.files; import java.io.File; +import java.io.IOException; import java.util.zip.ZipEntry; import org.slf4j.Logger; @@ -14,14 +15,24 @@ public class ZipSecurity { private ZipSecurity() {} - private static boolean isInSubDirectory(File base, File file) { - if (file == null) { + private static boolean isInSubDirectoryInternal(File baseDir, File canonFile) { + if (canonFile == null) { return false; } - if (file.equals(base)) { + if (canonFile.equals(baseDir)) { return true; } - return isInSubDirectory(base, file.getParentFile()); + return isInSubDirectoryInternal(baseDir, canonFile.getParentFile()); + } + + public static boolean isInSubDirectory(File baseDir, File file) { + try { + file = file.getCanonicalFile(); + } + catch(IOException e) { + return false; + } + return isInSubDirectoryInternal(baseDir, file); } // checks that entry name contains no any traversals @@ -30,7 +41,7 @@ public class ZipSecurity { try { File currentPath = new File(".").getCanonicalFile(); File canonical = new File(currentPath, entryName).getCanonicalFile(); - if (isInSubDirectory(currentPath, canonical)) { + if (isInSubDirectoryInternal(currentPath, canonical)) { return true; } LOG.error("Path traversal attack detected, invalid name: {}", entryName); diff --git a/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java b/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java index 874e824cd..2eb608760 100644 --- a/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java +++ b/jadx-core/src/main/java/jadx/core/xmlgen/ResourcesSaver.java @@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory; import jadx.api.ResourceFile; import jadx.api.ResourceType; import jadx.core.codegen.CodeWriter; +import jadx.core.utils.files.ZipSecurity; import static jadx.core.utils.files.FileUtils.prepareFile; @@ -60,12 +61,25 @@ public class ResourcesSaver implements Runnable { String ext = FilenameUtils.getExtension(outFile.getName()); try { outFile = prepareFile(outFile); + + if(!ZipSecurity.isInSubDirectory(outDir, outFile)) { + LOG.error("Path traversal attack detected, invalid resource name: {}", + outFile.getPath()); + return; + } + ImageIO.write(image, ext, outFile); } catch (IOException e) { LOG.error("Failed to save image: {}", rc.getName(), e); } return; } + + if(!ZipSecurity.isInSubDirectory(outDir, outFile)) { + LOG.error("Path traversal attack detected, invalid resource name: {}", + rc.getFileName()); + return; + } saveToFile(rc, outFile); }