refactor: fix zip security in dex plugin, remove smali deps from jadx-core

This commit is contained in:
Skylot
2020-08-06 13:04:45 +01:00
parent 558a86739f
commit 1560284831
25 changed files with 152 additions and 209 deletions
@@ -1,6 +1,5 @@
package jadx.api.plugins.input.data;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Consumer;
@@ -23,7 +22,7 @@ public interface IClassData {
String getSourceFile();
Path getInputPath();
String getInputFileName();
void visitFieldsAndMethods(Consumer<IFieldData> fieldsConsumer, Consumer<IMethodData> mthConsumer);
@@ -31,6 +30,5 @@ public interface IClassData {
List<IAnnotation> getAnnotations();
// TODO: make api methods to get dissembled code
int getClassDefOffset();
String getDisassembledCode();
}
@@ -0,0 +1,76 @@
package jadx.api.plugins.utils;
import java.io.File;
import java.io.IOException;
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 = 100;
private ZipSecurity() {
}
private static boolean isInSubDirectoryInternal(File baseDir, File canonFile) {
if (canonFile == null) {
return false;
}
if (canonFile.equals(baseDir)) {
return true;
}
return isInSubDirectoryInternal(baseDir, canonFile.getParentFile());
}
public static boolean isInSubDirectory(File baseDir, File file) {
try {
file = file.getCanonicalFile();
baseDir = baseDir.getCanonicalFile();
} catch (IOException e) {
return false;
}
return isInSubDirectoryInternal(baseDir, file);
}
// checks that entry name contains no any traversals
// and prevents cases like "../classes.dex", to limit output only to the specified directory
public static boolean isValidZipEntryName(String entryName) {
try {
File currentPath = new File(".").getCanonicalFile();
File canonical = new File(currentPath, entryName).getCanonicalFile();
if (isInSubDirectoryInternal(currentPath, canonical)) {
return true;
}
LOG.error("Path traversal attack detected, invalid name: {}", entryName);
return false;
} catch (Exception e) {
LOG.error("Path traversal attack detected, invalid name: {}", entryName);
return false;
}
}
public static boolean isZipBomb(ZipEntry entry) {
long compressedSize = entry.getCompressedSize();
long uncompressedSize = entry.getSize();
if (compressedSize < 0 || uncompressedSize < 0) {
LOG.error("Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {}",
compressedSize, uncompressedSize, entry.getName());
return true;
}
if (compressedSize * MAX_SIZE_DIFF < uncompressedSize) {
LOG.error("Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {}",
compressedSize, uncompressedSize, entry.getName());
return true;
}
return false;
}
public static boolean isValidZipEntry(ZipEntry entry) {
return isValidZipEntryName(entry.getName())
&& !isZipBomb(entry);
}
}