Я загрузил Мое приложение в Google Play Store, и Google выдал предупреждение «Android Security».
В приложении мы загрузили папку Zip и сохранили эту папку Zip во внутреннем хранилище, а затем распаковали еепапка во внутреннем хранилище устройства.
вот код папки UnZip:
public static void doUnzip(String inputZipFile, String
destinationDirectory, ZipProgressListener zipProgressListener) throws
IOException, RuntimeException {
Log.e(TAG, "doUnzip:inputZipFile: " + inputZipFile);
Log.e(TAG, "doUnzip:destinationDirectory: " + destinationDirectory);
int BUFFER = 6 * 1024;
List zipFiles = new ArrayList();
File sourceZipFile = FileUtils.createValidFile(inputZipFile);
File unzipDestinationDirectory =
FileUtils.createValidFile(destinationDirectory);
unzipDestinationDirectory.mkdir();
String newPath = unzipDestinationDirectory.getAbsolutePath() +
File.separator +
FileUtils.getFileNameWithoutExtension(sourceZipFile.getName());
new File(newPath).mkdir();
ZipFile zipFile;
// Open Zip file for reading
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
int entries = zipFile.size();
int total = 0;
Log.e(TAG, "doUnzip: entries Found !!" + entries);
// Create an enumeration of the entries in the zip file
Enumeration zipFileEntries = zipFile.entries();
if (zipProgressListener != null) {
zipProgressListener.onZipStart();
}
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
Log.i(TAG, "[doUnzip] " + currentEntry);
File file = new File(newPath);
File destFile = new File(newPath, currentEntry);
Log.i(TAG, "doUnzip getCanonicalPath : " +
destFile.getCanonicalPath());
if (Build.VERSION.SDK_INT <= VERSION_CODES.LOLLIPOP) {
Log.i(TAG, "doUnzip: LOLLIPOP");
if
(!destFile.getCanonicalPath().startsWith(destinationDirectory)) {
throw new RuntimeException(destFile.getCanonicalPath() +
" is outside of targetDirectory: " + destinationDirectory);
}
} else {
Log.i(TAG, "doUnzip: Above ");
if(!destFile.getCanonicalPath().contains(file.getName()) &&
!destFile.getCanonicalPath().contains("/")){
throw new RuntimeException(destFile.getCanonicalPath() +
" is outside of targetDirectory: " + destinationDirectory);
}
}
if (currentEntry.endsWith(".zip")) {
zipFiles.add(destFile.getAbsolutePath());
}
// grab file's parent directory structure
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is = new
BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
Log.e(TAG, "unzip:outPath: =>" +
destFile.getAbsolutePath() + "\nFile size: " + destFile.length()
/ 1024);
dest.flush();
dest.close();
is.close();
}
int progress = 0;
if (zipProgressListener != null) {
progress = (total++ * 100 / entries);
zipProgressListener.onZipProgressUpdate(progress);
}
Log.e(TAG, "unzip: PROGRESS::" + progress);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
zipFile.close();
for (Object zipFile1 : zipFiles) {
String zipName = (String) zipFile1;
Log.i(TAG, "doUnzip: ");
doUnzip(zipName, destinationDirectory + File.separator +
zipName.substring(0, zipName.lastIndexOf(".zip")),
zipProgressListener);
}
if (zipProgressListener != null) {
Log.i(TAG, "doUnzip: " + sourceZipFile.getName());
zipProgressListener.onZipCompleted(destinationDirectory +
File.separatorChar + sourceZipFile.getName().substring(0,
sourceZipFile.getName().lastIndexOf(".zip")));
}
}
Вот предупреждение Google:
Эта информация предназначена для разработчиков с приложениями, которые содержат небезопасные шаблоны разархивирования, что потенциально может привести к атаке Zip Path Traversal.Расположение уязвимых классов приложений, содержащих небезопасные шаблоны разархивирования, можно найти в уведомлении Play Console для вашего приложения.
Дополнительные сведения
Zip-файлы могут содержать запись (файл или каталог), содержащую символы обхода пути(«../») в его названии.Если разработчики разархивируют такие записи в ZIP-файле без проверки их имени, это может привести к атаке обхода пути, приводящей к записи в произвольные каталоги или даже к перезаписи файлов в личных папках приложения.
Рекомендуем исправить эту проблему вваше приложение, проверив, находятся ли канонические пути к разархивированным файлам в ожидаемом каталоге.В частности, перед использованием объекта File, созданного с использованием возвращаемого значения метода getName () ZipEntry, всегда проверяйте, принадлежит ли возвращаемое значение File.GetCanonicalPath () указанному пути к каталогу.Например:
InputStream is = new InputStream(untrustedFileName);
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
while((ZipEntry ze = zis.getNextEntry()) != null) {
File f = new File(DIR, ze.getName());
String canonicalPath = f.getCanonicalPath();
if (!canonicalPath.startsWith(DIR)) {
// SecurityException
}
// Finish unzipping…
}
Как я могу решить это предупреждение в Android OS-6 выше?