Как безопасно обнулить и освободить все страницы памяти, используемые приложением Android? - PullRequest
4 голосов
/ 27 февраля 2020

Я инженер-программист, создающий приложение Android, которое будет использоваться государственным учреждением.

Одним из требований нашего контракта является то, что приложение должно соответствовать требованиям FIPS 140. https://en.wikipedia.org/wiki/FIPS_140

Для соответствия требованиям FIPS наше приложение должно обнулять и очищать любые объекты паролей в ОЗУ, когда приложение android закрыто. (Обнуляя и удаляя пароль из ОЗУ, мы сокращаем окно возможностей для злоумышленников. То есть это снижает риск атаки при «холодной» загрузке: https://en.wikipedia.org/wiki/Cold_boot_attack)

Чтобы удовлетворить это требование, мы Первоначально следовал совету в следующих двух сообщениях SO, чтобы записать пароль пользователя как CharArray вместо строки

//First collect the password from Edit Text as a []char
int pl = passwordEditText.length();
char[] password = new char[pl];
passwordEditText.getText().getChars(0, pl, password, 0);

//Now set the password on viewmodel
viewModel.setPassword(password) 

Получив пароль, мы используем его для вызова сторонней библиотеки веб-сервисов, которая извлекает данные для отображения на экране.

Псевдокод ViewModel:

public DataObject getData(char[] password){
     return this.webService.getData(password);
}

Когда пользователь завершит работу с нашим приложением, мы вызываем следующий метод для обнуления и сброса пароля

Псевдокод ViewModel:

public zeroPassword(){
    Arrays.fill(this.password, 0);
    this.password = null;
}

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

HOWEVER ...

Копаем в стороннем коде WebService ( this.webService. getData (пароль) ) и оказывается, что под прикрытием веб-служба преобразует пароль массива char в строку, а затем передает его перед выполнением сетевого вызова.

В основном - даже если мы обнулите ссылку на массив char в нашем Android коде ViewModel, поскольку массив char берется сторонней библиотекой и используется для создания строки, пароль все равно будет существовать в памяти: (

OPTIONS

На данный момент мы рассматриваем два варианта:

  1. Вариант 1 - получить копию сторонней библиотеки и изменить ее так, чтобы что он не работает со строками пароля. Таким образом, мы можем изменить любое использование строки пароля для использования массивов символов, буферов и т. Д. c - все объекты, которые мы можем обнулить в какой-то момент)
  2. Вариант 2 - Мы исследуем какой-то способ обнулить и очистить все страницы памяти, используемые нашим приложением android (т.е. закрыть все приложение и очистить ОЗУ), когда пользователь закрывает приложение.

Как команда, мы предпочитаем вариант 2, потому что он будет охватывать все наши базы. Вариант 1 будет сложным, инвазивным, трудоемким и грязным.

ОБНОВЛЕНИЕ - Исходя из приведенного здесь ответа, кажется, что Вариант 1 даже не работает Как я могу убедиться уничтожение объекта String в Java? Java использует сборку мусора поколений и копирует объекты повсеместно, даже массивы символов, поэтому обнуление массивов символов не гарантирует удаление пароля из ОЗУ.

Есть ли способ выполнить sh то, что нас попросили сделать? т.е. полностью стереть следы пароля из памяти?

Могут ли android эксперты по безопасности подсказать?

Спасибо

Ответы [ 2 ]

0 голосов
/ 08 марта 2020

Использование V8 для запуска работника сервиса при закрытии приложения, например что-то вроде:

addEventListener("fetch", event => {
    event.respondWith(fetchAndReplace(event.request));
});
async function fetchAndReplace(request) {
    const response = await fetch(request);
    let type = response.headers.get("Content-Type") || "";
    if (!type.startsWith("application/")) {
        return response;
    }

    let newHeaders = new Headers(response.headers);

    newHeaders.set('Clear-Site-Data', '"cache", "cookies",  "storage",  
    "executionContexts"');

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

См. Clear-Site-Data в MDN. «Сайт» вводит в заблуждение как «сайт» ~ = только веб-сайты.

0 голосов
/ 03 марта 2020

Согласно Документам ViewModel :

Когда действие владельца завершается, платформа вызывает метод ViewModel объектов onCleared () , так что он может очищать ресурсы .

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

Чтобы облегчить понимание, ViewModel имеет следующее поведение:

  • Когда действие воссоздается при изменениях конфигурации : мы все еще есть тот же экземпляр ViewModel.

  • Когда Activity завершится : ViewModel автоматически вызовет onCleared() для очистки ресурсов для нас, поэтому у нас даже нет выполнить ручное открепление / очистку.

Причина, по которой некоторые объекты ViewModel все еще существуют в памяти, заключается в том, что Activity (в которой есть ViewModel) все еще активна, ИЛИ там может быть другой кл задница, которая содержит ссылку на эту деятельность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...