1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Flutter-TL.md 13 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 10.03.2025 00:06 5767d61

Исследование проблемы безопасной утечки данных в Flutter при использовании компонента TextField

Flutter компонент TextField, наверняка знакомый всем, часто используется как входной контроль для ввода данных, особенно в сценариях аутентификации, таких как ввод пароля. При этом конфигурация obscureText: true обеспечивает зашифрованный вид вводимых данных.

При успешной авторизации страница обычно уничтожается вместе со всей связанной информацией пользователя, но действительно ли данные пароля уничтожаются?

1. CWE-316

Если вы используете TextField для ввода паролей, то вы можете столкнуться с предупреждением безопасности типа CWE-316. Основная причина этого — Flutter хранит в памяти открытый текст введенных данных во время взаимодействия с платформой.

Для воспроизведения этой проблемы вам потребуется инструмент для чтения данных оперативной памяти вашего приложения во время его выполнения. В данном случае рекомендовано использовать apk-medit.

Шаги использования apk-medit:- Скачайте и распакуйте apk-medit для получения исполняемого файла medit.

  • Подключите ваш телефон через USB для отладки без необходимости делать rooted устройство.
  • Выполните команду adb push medit /data/local/tmp/medit для передачи исполняемого файла на устройство.
  • Выполните команду adb shell для доступа к командной строке устройства.
  • Выполните команду run-as <target-package-name>, где <target-package-name> — это имя вашего пакета.
  • Выполните команду cp /data/local/tmp/medit ./medit для копирования исполняемого файла.
  • Выполните команду ./medit для запуска режима просмотра памяти.Успешно запустив инструмент, вы должны увидеть состояние готовности, показанное на следующем рисунке:

Затем введите в поле ввода пароль "abcd12345" и выполните команду find abcd12345 в терминале. Вы найдете семь связанных записей в категории String.

image-20220426115105174

Следующим шагом будет очистка введенного текста с помощью контроллера TextField, удаление текущего экрана и переход на чистый экран. После этого активируйте сборку мусора в Flutter DevTools. Наконец, снова выполните команду find abcd12345. Результаты будут следующими:

image-20220426115504463

При этом в памяти остаются еще 5 связанных данных. Выберите один адрес, например 0x7194a57b, и выполните команду dump: dump 0x7194a500 0x7194a5ff. Результат показан ниже:

Эта проблема существует на многих платформах, таких как Android, iOS и Linux. Но откуда она берется? Для этого стоит рассмотреть процесс ввода текста в Flutter.

Второй раздел: Процесс ввода текста

Как кросс-платформенная система, Flutter использует каналы платформы для ввода текстовых данных. Например, на Android это реализуется через систему InputConnection.На Android, когда клавиатура хочет взаимодействовать с некоторыми View, система вызывает метод onCreateInputConnection объекта View, который возвращает экземпляр InputConnection для использования клавиатурой. Разработчики могут переопределить некоторые методы InputConnection, чтобы перехватывать ввод или реагировать на определённые ключевые события.Например, контроллер EditText поддерживает ввод текста, поскольку его родительский класс TextView реализует EditableInputConnection и переопределяет метод onCreateInputConnection объекта View.

image-20220426084518804Аналогично, в Flutter объект FlutterView также переопределяет метод onCreateInputConnection и реализует InputConnectionAdaptor для взаимодействия. Здесь мы кратко представляем объекты, которые будут использоваться далее:

  • InputConnectionAdaptor: реализация InputConnection, используемая для взаимодействия между клавиатурой и Flutter, внутри которой содержатся объекты: TextInputChannel, ListenableEditingState, InputMethodManager, KeyboardManager и др.;
  • TextInputChannel: упакованное в объект MethodChannel, которое используется для взаимодействия с Dart и выполнения некоторых логических операций;
  • InputMethodManager: объект управления клавиатурой Android, который позволяет показывать/скрывать клавиатуру или конфигурировать некоторые характеристики клавиатуры;
  • ListenableEditingState: используется для хранения текущего состояния редактирования, таких как содержание текста, диапазон выделения и т. д., так как InputConnection требует интерфейса Editable, а это его подкласс. Внутри Android framework содержимое и состояние ввода через клавиатуру управляются через интерфейс Editable;
  • TextInputPlugin: выполняет роль аналогичную роли FlutterPlugin, владея TextInputChannel и InputMethodManager для выполнения некоторых логических операций связанных с вводом. Кроме того, сам он также реализует интерфейс ListenableEditingState.EditingStateWatcher, вызываемый при вводе текста;

Представив функционал этих объектов, вернёмся к процессу ввода текста.Когда вы вводите текст с клавиатуры, введенный текст попадает в метод endBatchEdit класса InputConnectionAdaptor, после чего происходит следующее:- Введённый текст сохраняется в объекте ListenableEditingState (параметр mEditable в исходном коде);

  • Затем отправляется уведомление в TextInputPlugin для форматирования данных и передачи их через TextInputChannel;
  • Далее данные упаковываются в формате Map и передаются в метод updateEditingState класса TextInputClient на стороне Dart;
  • После получения данных в виде Map, уровень Dart обновляет значение в объекте TextEditingValue, что приводит к отображению введённого текста.

Как видно, основной процесс заключается в том, чтобы взаимодействовать с InputConnectionAdaptor для получения введённого текста и состояния, затем упаковывать эти данные в Map и передавать их на уровень Dart, где они расшифровываются и отображаются.

Перейдём теперь к проблеме CWE-316. В данном случае, временно сохранённые в памяти открытые пароли находятся именно в методе TextInputClient.updateEditingState, то есть в переданном из нативного уровня в Dart Map. Эти данные остаются в памяти после передачи, что может привести к утечкам информации.

На самом деле, эта проблема была обсуждена в issue Flutter #84708. Хотя официальная классификация проблемы указывает на её приоритет P3, ответы свидетельствуют о том, что проблема CWE-316 скорее всего является следствием недопонимания, так как если третья сторона имеет доступ к данным устройства, то практически невозможно полностью защититься от утечек.Кроме того, анализ текущего дизайна Dart показывает, что объекты типа String являются неизменяемыми. Как только открытый String попадает в кучу Dart (heap), его удаление становится неопределенным. Даже после сборки мусора (GC) содержимое памяти остаётся нетронутым до тех пор, пока весь участок памяти не будет очищен и не будет возвращён операционной системой или заново использован для хранения нового объекта.

Дополнительно стоит отметить два аспекта работы InputConnectionAdaptor: методы performEditorAction и sendKeyEvent.

  • performEditorAction: Когда специальные клавиши ввода, такие как IME_ACTION_GO, IME_ACTION_SEND, IME_ACTION_DONE, нажимаются, то через TextInputChannel код сразу передаётся в Dart;
  • sendKeyEvent: При нажатии некоторых специальных кнопок происходит обратный вызов, например, при нажатии кнопки Backspace, но это зависит от используемого ввода; например, кнопка Backspace в безопасной клавиатуре Xiaomi не вызывает этот обратный вызов, однако цифровые кнопки этой же клавиатуры вызывают;

3. Последнее

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

Конечно, если вы используете только строки вместо EditableText, возможности Dart, такие как типизированные данные или указатели FFI, могут частично решить эту проблему.Если у вас есть какие-либо идеи относительно CWE-316 для TextField, пожалуйста, оставьте ваши комментарии для обсуждения!

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/CarGuo-GSYFlutterBook.git
git@api.gitlife.ru:oschina-mirror/CarGuo-GSYFlutterBook.git
oschina-mirror
CarGuo-GSYFlutterBook
CarGuo-GSYFlutterBook
master