
Подробности CVE-2020-14292
В приложении COVIDSafe для Android версии до 1.0.21 включительно небезопасное использование опции транспортного протокола Bluetooth в GATT-соединении позволяет злоумышленникам обманом заставить приложение установить соединение через Bluetooth-транспорт BR/EDR, что раскрывает публичный Bluetooth-адрес телефона жертвы без авторизации, обходя защиту рандомизации Bluetooth-адреса на телефоне пользователя. Эта проблема отслеживается под идентификатором CVE-2020-14292.
Причина проблемы кроется в функции startWork, где GATT-соединение устанавливается с помощью connectGatt, но не была указана опция транспорта.
fun startWork(
context: Context,
gattCallback: StreetPassWorker.StreetPassGattCallback
) {
gatt = device.connectGatt(context, false, gattCallback)
if (gatt == null) {
CentralLog.e(TAG, "Unable to connect to ${device.address}")
}
}
Это приведёт к тому, что Android будет использовать опцию TRANSPORT_AUTO для транспорта при инициировании Bluetooth-соединения. Похоже, что в реализации Android по умолчанию будет выбран BR/EDR, если подключаемое периферийное устройство является двухрежимным (поддерживает как BR/EDR, так и LE); это может быть связано со следующей реализацией GATT-клиента в Android, см., например, этот код (соответствующий фрагмент кода приведён ниже):
// Determine transport
if (transport_p != BT_TRANSPORT_AUTO) {
transport = transport_p;
} else {
switch (device_type) {
case BT_DEVICE_TYPE_BREDR:
transport = BT_TRANSPORT_BR_EDR;
break;
case BT_DEVICE_TYPE_BLE:
transport = BT_TRANSPORT_LE;
break;
case BT_DEVICE_TYPE_DUMO:
if (transport_p == BT_TRANSPORT_LE)
transport = BT_TRANSPORT_LE;
else
transport = BT_TRANSPORT_BR_EDR;
break;
}
Поскольку рандомизация MAC-адреса не поддерживается в BR/EDR, центральное устройство раскроет свой идентификационный адрес периферийному устройству.
Для запуска атаки злоумышленник рекламирует GATT-сервер на двухрежимном устройстве (BR/EDR + LE), используя публичный адрес (эта часть важна, иначе понижение версии не произойдёт и центральное устройство Android будет использовать LE-транспорт). Это заставит приложение COVIDSafe использовать транспорт BR/EDR вместо LE-транспорта для подключения к периферийному устройству, что приведёт к раскрытию публичного адреса телефона. Это работает для всех протестированных телефонов и версий Android.
Для Android 6 и более поздних версий исправление простое: нужно явно указать опцию транспорта.
gatt = device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE)
Однако это не работает для Android 5.1 (API Level 22), поскольку этот метод не доступен в API. На самом деле он существует, но является скрытым. Поэтому для Android 5.1 возможное исправление включает использование рефлексии для вызова этого скрытого метода. Эти исправления были реализованы в COVIDSafe (Android) v1.0.48.
Однако исправление для Android 5.1 может работать не всегда; мои тесты показали, что всё ещё происходит утечка идентификационных адресов. Это может быть связано с неудачей техники рефлексии во время выполнения; потребуются дальнейшие исследования.
Обладание идентификационным адресом телефона позволит злоумышленнику отслеживать телефон, когда его Bluetooth включён и он находится в радиусе действия Bluetooth злоумышленника. Некоторые уязвимости, связанные с Bluetooth (например, CVE-2020-0022), полагаются на знание идентификационного адреса для проведения дальнейших атак, поэтому существует потенциал объединения этой атаки с другими. См. этот документ о некоторых последствиях обладания злоумышленником идентификационным адресом.
Пользователям Android-версии приложения COVIDSafe настоятельно рекомендуется обновить приложение. Для тех, кто использует Android 5, рекомендуется отключать Bluetooth в ситуациях, когда его функциональность не требуется.
Эта проблема была впервые сообщена в Агентство по цифровой трансформации правительства Австралии 2 июня 2020 года. Первое исправление было выпущено 22 июня 2020 года для Android 6 и выше. Подтверждено, что оно работает на Android 6 и выше. Но проблема по-прежнему затрагивала Android 5.1. Второе исправление, выпущенное 30 июля 2020 года, решило оставшуюся проблему с Android 5.1.
Спасибо Jim Mussared за независимое подтверждение этой проблемы и за различные обсуждения, связанные с этой проблемой.