Перейти к содержанию

Возможность перезаписи файлов в приватной директории приложения при работе с zip-архивами

Критичность: ВЫСОКИЙ

Описание

Выявленная уязвимость относится к конкретному сценарию, при котором возможно перезаписать приватные файлы приложения, эксплуатируя сочетание zip-архива и уязвимости обхода пути (Path Traversal). Уязвимость обхода пути (Path Traversal) — это тип уязвимости, при котором злоумышленник может манипулировать путем к файлу с целью получить доступ к файлам или каталогам за пределами предполагаемой директории. Проще говоря, это означает, что злоумышленник может «пройти» по файловой системе выше и получить доступ к файлам, к которым он не должен иметь доступ, к примеру через указание пути ../../../.

Примерный сценарий атаки:

  1. Злоумышленник создает специально подготовленный zip-архив, содержащий файл с путем, включающим последовательность обхода пути. Например, файл внутри zip-архива может иметь путь ../../data/private_file.txt.

  2. Злоумышленник убеждает целевого пользователя загрузить и извлечь вредоносный zip-архив на своем устройстве Android. Это может быть достигнуто средствами социальной инженерии, например, через вредоносный веб-сайт, электронное письмо с вредоносным вложением или другими способами. Либо атака может быть направлена на обход локальных проверок, например, если аутентификация по pin-коду осуществлена локально, возможно перезаписать файл, содержащий значение кода, на свой и войти в приложение.

  3. При извлечении zip-архива, если не выполняется должная проверка путей файлов внутри архива, злоумышленник может перезаписать приватные файлы.

В зависимости от файла, на который направлена атака, это может потенциально привести к несанкционированному раскрытию конфиденциальной информации или изменению важных данных.

Пример уязвимого кода.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipExtractor {
    public static void extractZip(String zipFilePath, String destinationPath) {
        try {
            File destDir = new File(destinationPath);
            byte[] buffer = new byte[1024];

            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
            ZipEntry zipEntry = zipInputStream.getNextEntry();

            while (zipEntry != null) {
                String entryName = zipEntry.getName();
                String entryPath = destinationPath + File.separator + entryName;

                File outputFile = new File(entryPath);
                outputFile.getParentFile().mkdirs();

                FileOutputStream fos = new FileOutputStream(outputFile);

                int length;
                while ((length = zipInputStream.read(buffer)) > 0) {
                    fos.write(buffer, 0, length);
                }

                fos.close();
                zipEntry = zipInputStream.getNextEntry();
            }

            zipInputStream.closeEntry();
            zipInputStream.close();

            System.out.println("Zip extraction complete.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String zipFilePath = "/path/to/malicious.zip"; // Path to the malicious zip-archive
        String destinationPath = "/data/private/"; // Destination directory for extracting files

        extractZip(zipFilePath, destinationPath);
    }
}

В этом коде метод extractZip() отвечает за извлечение файлов из zip-архива. Однако он некорректно фильтрует пути к файлам, что делает его уязвимым для атак Path Traversal. Например, если destinationPath установлен на /data/private/, злоумышленник может создать файл с путем ../../data/private_file.txt внутри zip-архива. Когда уязвимый код извлекает архив, он добавляет путь к файлу к destinationPath, что в итоге даст путь к /data/private/../../data/private_file.txt. В результате злоумышленник получает доступ к private_file.txt и сможет перезаписать его.

Чтобы устранить эту уязвимость, необходимо проводить правильную валидацию и санитизацию входных данных, связанных с путями к файлам. Этого можно достичь сравнением путей к файлам с ожидаемой структурой каталогов с целью убедиться, что извлеченные файлы находятся в предназначенном каталоге.

Рекомендации

Чтобы устранить уязвимость и предотвратить атаки с Path Traversal, необходимо реализовать проверку ввода и санитизировать пути к файлам. Например, в представленном выше коде это можно исправить следующим образом.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipExtractor {
    public static void extractZip(String zipFilePath, String destinationPath) {
        try {
            File destDir = new File(destinationPath);
            byte[] buffer = new byte[1024];

            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
            ZipEntry zipEntry = zipInputStream.getNextEntry();

            while (zipEntry != null) {
                String entryName = zipEntry.getName();
                String entryPath = sanitizeFilePath(destinationPath, entryName);

                if (entryPath != null) {
                    File outputFile = new File(entryPath);
                    outputFile.getParentFile().mkdirs();

                    FileOutputStream fos = new FileOutputStream(outputFile);

                    int length;
                    while ((length = zipInputStream.read(buffer)) > 0) {
                        fos.write(buffer, 0, length);
                    }

                    fos.close();
                }

                zipEntry = zipInputStream.getNextEntry();
            }

            zipInputStream.closeEntry();
            zipInputStream.close();

            System.out.println("Zip extraction complete.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String sanitizeFilePath(String destinationPath, String entryName) {
        // Ensure that the entry name does not contain any path traversal sequences
        String sanitizedEntryName = entryName.replace("..", "").replace("/", "").replace("\\", "");

        // Check if the resulting path is within the intended destination directory
        String entryPath = destinationPath + File.separator + sanitizedEntryName;
        File destinationDir = new File(destinationPath);

        if (!destinationDir.toPath().normalize().equals(new File(entryPath).toPath().normalize())) {
            // Abort extraction if the entry path is outside the intended directory
            System.err.println("Invalid file path: " + entryPath);
            return null;
        }

        return entryPath;
    }

    public static void main(String[] args) {
        String zipFilePath = "/path/to/malicious.zip"; // Path to the malicious zip-archive
        String destinationPath = "/data/private/"; // Destination directory for extracting files

        extractZip(zipFilePath, destinationPath);
    }
}

В обновленном коде введен метод sanitizeFilePath(), который выполняет валидацию и санитизацию путей к извлеченным файлам. Вот как это работает:

  1. Метод принимает destinationPath (предполагаемый каталог для извлечения файлов) и entryName (имя файла внутри zip-архива) в качестве входных данных.

  2. Метод очищает entryName путем удаления любых последовательностей обхода пути, таких как .., прямых (/) и обратных (\) слэшей.

  3. Затем он добавляет очищенный entryName к destinationPath для получения полного пути entryPath.

  4. Метод сравнивает нормализованную версию entryPath с нормализованной версией destinationPath, чтобы убедиться, что извлеченный файл будет находиться в предполагаемом каталоге. Несовпадение путей указывает на то, что путь к файлу пытается выйти за пределы предполагаемой структуры каталогов и процесс извлечения прерывается.

В результате этих модификаций код выполняет валидацию входных данных и предотвращает атаки прохода по пути, убеждаясь, что извлеченные файлы остаются в предполагаемом каталоге назначения.

Чтобы предотвратить подобные уязвимости, необходимо придерживаться основных принципов:

  1. Валидация и санитизация ввода. Необходимо реализовать надежные механизмы валидации входных данных, особенно имен и путей файлов, контролируемых пользователем. Входные данные необходимо проверять на соответствие белому списку разрешенных символов.

  2. Использование абсолютных путей к файлам. При доступе к файлам вместо относительных путей используйте абсолютные. Это гарантирует, что операции с файлами будут явно ограничены определенными каталогами и предотвращает непреднамеренный обход пути.

  3. Избегайте путей, контролируемых пользователем. Минимизируйте использование входных данных, контролируемых пользователем, особенно для функциональности, связанной с файлами. Если необходимо использовать пользовательский ввод, тщательно валидируйте его перед использованием.

  4. Используйте белый список разрешенных имен и путей файлов. Создайте белый список разрешенных имен/путей файлов и валидируйте ввод на соответствие этому списку. Запрещайте или очищайте любой ввод, который не соответствует заранее определенной структуре или шаблонам.

  5. Используйте безопасные API и библиотеки для работы с файлами. Используйте безопасные файловые API и библиотеки, которые обеспечивают встроенную защиту от атак Path Traversal. Во многих библиотеках защита от данной уязвимости уже реализована.

  6. Регулярно обновляйте зависимости. Следите за актуальностью всех зависимостей, включая фреймворки и библиотеки, с помощью последних патчей безопасности. Уязвимости в коде сторонних разработчиков могут внести риск прохода по пути в ваше приложение. Будьте в курсе информации о безопасности и своевременно обновляйте зависимости.

Ссылки

  1. https://developer.android.com/topic/security/risks/zip-path-traversal
  2. https://stackoverflow.com/questions/56303842/fixing-a-zip-path-traversal-vulnerability-in-android
  3. https://support.google.com/faqs/answer/7496913?hl=en
  4. https://hackerone.com/reports/859469
К началу