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

Возможность получения доступа к произвольному файлу

Критичность: СРЕДНИЙ
Способ обнаружения: IAST

Описание

Уязвимость позволяет получить доступ к произвольным файлам приложения.

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

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

private void takeSomeSharedFile() {
Intent interceptableIntent = new Intent("vuln.app.pkg.INTERCAPTABLE");
startActivityForResult(interceptableIntent, 1001);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == -1 && data != null) {
    if(requestCode == 1001) {
    copyToCache(data.getData());
    }
}
}

public static File copyToCache(Uri uri) {
try {
    File out = new File(getExternalCacheDir(), "" + System.currentTimeMillis());
    InputStream i = getContentResolver().openInputStream(uri);
    OutputStream o = new FileOutputStream(out);
    IOUtils.copy(i, o);
    i.close();
    o.close();
    return out;
}
catch (Exception e) {
    return null;
}
}

Вредоносное приложение может использовать такой код:

Intent intent = new Intent();
File privFile = new File("/data/data/vuln.app.pkg/databases/main.db");
intent.setData(Uri.fromFile(privFile));
setResult(RESULT_OK, intent);
finish();

В результате уязвимое приложение скопирует файл main.db в файл /storage/emulated/0/Android/data/vuln.app.pkg/1650464271, доступ к которому может получить вредоносное приложение.

Проблема

Если приложение использует пришедший извне Uri (или путь) для файловых операций без проверки, вредоносное приложение может с помощью символов обхода каталога (../) или прямого указания пути выйти за пределы разрешённого каталога. Это приводит к чтению или перезаписи произвольных файлов в приватной директории приложения, утечке конфиденциальных данных и, в зависимости от операции, к компрометации приложения.

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

Необходимо проводить валидацию canonical-пути файла непосредственно перед вызовом методов файловых операций над этим файлом.

Важно сравнивать префикс с канонизированным базовым каталогом, к которому добавлен завершающий разделитель (File.separator). Проверка вида canonicalPath.startsWith(sdcardDir) без разделителя обходится: например, для sdcardDir = "/data/files" путь /data/files_evil пройдёт проверку, хотя находится вне целевого каталога.

String canonicalDir = new File(sdcardDir).getCanonicalPath();
File file = new File(canonicalDir, uri.getLastPathSegment());
String canonicalPath = file.getCanonicalPath();
if (!canonicalPath.equals(canonicalDir)
        && !canonicalPath.startsWith(canonicalDir + File.separator)) {
    throw new IllegalArgumentException();
}

Дополнительно:

  • по возможности не принимайте от сторонних приложений произвольный Uri/путь, а используйте безопасные механизмы обмена файлами (FileProvider с заранее заданными путями);
  • проверяйте, что итоговый файл действительно является ожидаемой целью (например, лежит в выделенном подкаталоге);
  • не выполняйте файловые операции с повышенными привилегиями над путями, полученными извне.

Ссылки

  1. Path traversal
  2. Защита данных приложения
  3. FileProvider
К началу