diff --git a/jadx-core/src/main/java/jadx/api/ResourceFile.java b/jadx-core/src/main/java/jadx/api/ResourceFile.java index 182fb4f22..269c2c4f5 100644 --- a/jadx-core/src/main/java/jadx/api/ResourceFile.java +++ b/jadx-core/src/main/java/jadx/api/ResourceFile.java @@ -1,5 +1,6 @@ package jadx.api; +import jadx.core.utils.files.ZipSecurity; import jadx.core.xmlgen.ResContainer; import java.io.File; @@ -34,7 +35,7 @@ public class ResourceFile { private final ResourceType type; private ZipRef zipRef; - ResourceFile(JadxDecompiler decompiler, String name, ResourceType type) { + protected ResourceFile(JadxDecompiler decompiler, String name, ResourceType type) { this.decompiler = decompiler; this.name = name; this.type = type; @@ -64,4 +65,11 @@ public class ResourceFile { public String toString() { return "ResourceFile{name='" + name + '\'' + ", type=" + type + "}"; } + + public static ResourceFile createResourceFileInstance(JadxDecompiler decompiler, String name, ResourceType type) { + if(!ZipSecurity.isValidZipEntryName(name)) { + return null; + } + return new ResourceFile(decompiler, name, type); + } } diff --git a/jadx-core/src/main/java/jadx/api/ResourceFileContent.java b/jadx-core/src/main/java/jadx/api/ResourceFileContent.java index 409aa5435..d0880a1c5 100644 --- a/jadx-core/src/main/java/jadx/api/ResourceFileContent.java +++ b/jadx-core/src/main/java/jadx/api/ResourceFileContent.java @@ -1,13 +1,14 @@ package jadx.api; import jadx.core.codegen.CodeWriter; +import jadx.core.utils.files.ZipSecurity; import jadx.core.xmlgen.ResContainer; public class ResourceFileContent extends ResourceFile { private final CodeWriter content; - public ResourceFileContent(String name, ResourceType type, CodeWriter content) { + private ResourceFileContent(String name, ResourceType type, CodeWriter content) { super(null, name, type); this.content = content; } @@ -16,4 +17,11 @@ public class ResourceFileContent extends ResourceFile { public ResContainer loadContent() { return ResContainer.singleFile(getName(), content); } + + public static ResourceFileContent createResourceFileContentInstance(String name, ResourceType type, CodeWriter content) { + if(!ZipSecurity.isValidZipEntryName(name)) { + return null; + } + return new ResourceFileContent(name, type, content); + } } diff --git a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java index 38599df14..61a039274 100644 --- a/jadx-core/src/main/java/jadx/api/ResourcesLoader.java +++ b/jadx-core/src/main/java/jadx/api/ResourcesLoader.java @@ -157,8 +157,10 @@ public final class ResourcesLoader { private void addResourceFile(List list, File file) { String name = file.getAbsolutePath(); ResourceType type = ResourceType.getFileType(name); - ResourceFile rf = new ResourceFile(jadxRef, name, type); - list.add(rf); + ResourceFile rf = ResourceFile.createResourceFileInstance(jadxRef, name, type); + if(rf != null) { + list.add(rf); + } } private void addEntry(List list, File zipFile, ZipEntry entry) { @@ -167,9 +169,11 @@ public final class ResourcesLoader { } String name = entry.getName(); ResourceType type = ResourceType.getFileType(name); - ResourceFile rf = new ResourceFile(jadxRef, name, type); - rf.setZipRef(new ZipRef(zipFile, name)); - list.add(rf); + ResourceFile rf = ResourceFile.createResourceFileInstance(jadxRef, name, type); + if(rf != null) { + rf.setZipRef(new ZipRef(zipFile, name)); + list.add(rf); + } } public static CodeWriter loadToCodeWriter(InputStream is) throws IOException { 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 13eb9ff8d..8f9f8c257 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 @@ -3,7 +3,12 @@ package jadx.core.utils.files; import java.io.File; import java.util.zip.ZipEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ZipSecurity { + private static final Logger LOG = LoggerFactory.getLogger(ZipSecurity.class); + // size of uncompressed zip entry shouldn't be bigger of compressed in MAX_SIZE_DIFF times private static final int MAX_SIZE_DIFF = 5; @@ -24,9 +29,14 @@ public class ZipSecurity { try { File currentPath = new File(".").getCanonicalFile(); File canonical = new File(currentPath, entryName).getCanonicalFile(); - return isInSubDirectory(currentPath, canonical); + if(isInSubDirectory(currentPath, canonical)) { + return true; + } + LOG.debug("Path traversal attack detected, invalid name: {}", entryName); + return false; } catch(Exception e) { + LOG.debug("Path traversal attack detected, invalid name: {}", entryName); return false; } } @@ -37,7 +47,11 @@ public class ZipSecurity { if(compressedSize < 0 || uncompressedSize < 0) { return true; } - return compressedSize * MAX_SIZE_DIFF < uncompressedSize; + if(compressedSize * MAX_SIZE_DIFF < uncompressedSize) { + LOG.debug("Zip bomp attack detected, invalid sizes: compressed {}, uncompressed {}", compressedSize, uncompressedSize); + return true; + } + return false; } public static boolean isValidZipEntry(ZipEntry entry) { diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java index 16bc12da7..6affa73cd 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JResource.java @@ -101,8 +101,10 @@ public class JResource extends JNode implements Comparable { String resName = rc.getName(); String[] path = resName.split("/"); String resShortName = path.length == 0 ? resName : path[path.length - 1]; - ResourceFileContent fileContent = new ResourceFileContent(resShortName, ResourceType.XML, cw); - addPath(path, root, new JResource(fileContent, resName, resShortName, JResType.FILE)); + ResourceFileContent fileContent = ResourceFileContent.createResourceFileContentInstance(resShortName, ResourceType.XML, cw); + if(fileContent != null) { + addPath(path, root, new JResource(fileContent, resName, resShortName, JResType.FILE)); + } } } List subFiles = rc.getSubFiles();