
Реализация на Rust proof-of-concept инъекции нажатий клавиш Марка Ньюлина (CVE-2023-45866).
⚠️ Отказ от ответственности: только для исследовательских и образовательных целей
Этот проект — Proof of Concept (PoC), демонстрирующий инъекцию нажатий клавиш Bluetooth, переписанный на Rust. Он предназначен строго для образовательных и исследовательских целей в области безопасности.
Загружая, клонируя или используя этот код, вы соглашаетесь использовать его ответственно и в соответствии со всеми применимыми законами и нормативными актами.
Добро пожаловать в Rusty Injector — реализацию на Rust, вдохновлённую PoC-инъекцией нажатий клавиш Bluetooth Марка Ньюлина, связанную с CVE-2023-45866, CVE-2024-21306 и CVE-2024-0230.
В настоящее время этот репозиторий реализует только CVE-2023-45866, который использует уязвимости инъекции нажатий клавиш в BlueZ в операционной системе Linux.
Ниже приведён скриншот описания NIST, включая оценку CVSS :
Снимок 1 : Описание NIST для CVE-2023-45866.
Прежде чем вдаваться в детали, я рекомендую посмотреть презентацию Марка Ньюлина на конференции NullCon 2024, так как она даёт ясное и полное объяснение этих уязвимостей : Hi, My Name Is keyboard by Marc Newlin.. Я также подготовил видео, популяризирующее эту уязвимость. Вы найдёте его здесь : How a Simple Bluetooth Hack Can Hijack Your Device - Hi, my name is keyboard.
📌 Если вы заметите пропущенные моменты, области, которые можно упростить, или возможные ошибки в приведённом ниже объяснении, пожалуйста, не стесняйтесь изменять его и отправлять запрос на слияние. Я буду рад рассмотреть ваши правки и включить их в репозиторий.
Поскольку мы рассмотрели только уязвимость CVE-2023-45866, действующую для операционных систем Linux, мы объясним только процесс достижения этой конкретной эксплуатации, нацеленной на библиотеку BlueZ.
Прежде всего, вы должны понять, что эта уязвимость используется только на Bluetooth BR/EDR, поскольку она нацелена на профиль HID, основанный на этой технологии. Возможно, вы знаете, что архитектурная реализация Bluetooth разделена на несколько уровней, как модель OSI для протокола Ethernet, и это можно наблюдать на нашей схеме ниже.
Диаграмма 1 : Упрощённый стек Bluetooth BR/EDR (Basic Rate - Enhanced Data Rate). Самый нижний уровень стека представляет физический уровень с выделенной антенной, а верхний уровень соответствует прикладному уровню, который иногда называют операционной системой. Когда два устройства хотят связаться друг с другом, они проходят через эти разные уровни: сверху вниз для исходящих пакетов и снизу вверх для входящих bluetooth-пакетов.
После процесса обнаружения, когда устройства определяют, что хотят установить соединение, они переходят к процессу сопряжения. Этот процесс обеспечивает взаимную аутентификацию между устройствами и установление ключа шифрования, который затем используется для защиты связи.
Спецификация Bluetooth предлагает разные уровни аутентификации и безопасности. В зависимости от механизма, используемого для аутентификации, уровень безопасности связи может варьироваться. Устройства могут аутентифицироваться на основе периферийных устройств ввода и вывода, которыми они обладают, — эта концепция называется моделями сопряжения. Вы, вероятно, сталкивались с этим при сопряжении двух устройств, например, когда требовалось ввести PIN-код, отображаемый на другом устройстве.
Существует четыре модели сопряжения, определяемые возможностями ввода/вывода (I/O) устройств:
Ниже приведена таблица, показывающая, какая модель сопряжения используется в зависимости от возможностей наших IoT-устройств.
Диаграмма 2 : Таблица, иллюстрирующая модели сопряжения Bluetooth BR/EDR, вдохновлённая Bluetooth Core Specification v5.3 - 2.3.5.1 Selecting key generation method Table 2.8 : Mapping of IO cacpabilities to key generation method (page 1573). Для получения дополнительной информации о режимах безопасности и моделях сопряжения, пожалуйста, ознакомьтесь с этой интересной статьёй в блоге Thyrasec : Bluetooth Security : Classic & BLE !
Я уверен, вас заинтриговал метод 'Just Works', и именно здесь кроется наша уязвимость. Вот в чём проблема: этот метод устанавливает сопряжение без запроса подтверждения или взаимодействия с пользователем, не оставляя возможности проверить подлинность сопрягаемого устройства. В Linux-системах стек BlueZ по умолчанию принимал входящие запросы на сопряжение от устройств, классифицированных как NoInputNoOutput (для обеспечения обратной совместимости). Поистине «замечательное» дизайнерское решение, не так ли?
Снимок 2 : Обновление конфигурации blueZ по умолчанию для включения безопасности Bluetooth и исправления CVE-2023-45866.
После сопряжения с целевым устройством наша система устанавливает соединение с протоколом обнаружения служб (SDP) через порт 1 уровня L2CAP. Как показано на диаграмме 1, уровень L2CAP служит посредником между нижними и верхними сервисными уровнями, обеспечивая сегментацию, мультиплексирование и сборку пакетов данных. Через SDP-соединение мы идентифицируем все доступные службы на целевом устройстве и подключаемся к службе профиля HID (Human Interface Profile). Профиль HID, используемый операционными системами для обработки ввода с Bluetooth-клавиатур и мышей, работает через порты 17 (HID Control) и 19 (HID Interrupt) уровня L2CAP. Для доступа к профилю HID не требуется аутентификация, и любое устройство, подключённое к портам 17 и 19 L2CAP, распознаётся как HID-устройство.
Атакующий может выдать себя за службы и класс беспроводной Bluetooth-клавиатуры, использовать модель сопряжения 'Just Works', указав возможность 'NoInputNoOutput', и внедрять несанкционированные нажатия клавиш в целевое устройство.
Если быть полностью честным, единственной целью было переписать proof of concept на Rust, чтобы глубже понять тонкости этого эксплойта. Именно поэтому в этой первой итерации общая архитектура была вдохновлена python PoC Марка Ньюлина : Github "hi_my_name_is_keyboard". В будущей переработке его можно было бы реализовать в более «rusty» (идиоматичном для Rust) стиле.
Крейты (= библиотеки Rust), использованные при этой реализации :
[dependencies]
bluer = { version = "0.17.3", features = ["l2cap", "bluetoothd", "id", "rfcomm"] }
tokio = "1.42.0"
regex = "1.11.1"
clap = { version = "4.5.23", features = ["derive"] }
Ключевой зависимостью в моём проекте был 'BlueR,' — Rust API, построенный поверх оригинальной C-библиотеки BlueZ. С их работой можно ознакомиться здесь : GitHub BlueR. Я также интегрировал Tokio для использования async-функций, предоставляемых библиотекой BlueR. Кроме того, я использовал Clap — парсер аргументов командной строки, и Regex — крейт, реализующий регулярные выражения в Rust, для проверки пользовательского ввода для 'bt_addr' (Bluetooth-адрес).
После изучения реализации Марка Ньюлина я разбил архитектуру на несколько шагов для воспроизведения той же функциональности :
--iface или -i — указывает Bluetooth-интерфейс/адаптер для использования. Этот аргумент необязателен; если ничего не указано, будет предпринята попытка использовать интерфейс по умолчанию.--target или -t — обязателен и задаёт Bluetooth-адрес цели.NoInputNoOutput, чтобы получить доступ к методу сопряжения "Just Works" при соединении с целевым устройством.0x002540 для имитации клавиатуры.Я старался как можно больше комментировать свой код. Если вы его просмотрите, вы легко узнаете все эти шаги. Чтобы сделать его более элегантным, следующим шагом было бы сделать его более «rusty», с корректным завершением работы, и добавить ряд других функций, например возможность разбора скриптов клавиатуры (подготовленных полезных нагрузок) или графический интерфейс. Повторюсь, это было только в образовательных целях; не уверен, что буду работать над другими итерациями этой программы. Но, опять же, вклад приветствуется. Если у вас есть вопросы, не стесняйтесь задавать.
Первое, что следует отметить : Этот инструмент был разработан и протестирован на Ubuntu 24.04.
Чтобы использовать этот инструмент, вам нужно отключить службу HID по умолчанию, зарегистрированную BlueZ, чтобы её можно было перерегистрировать при запуске эксплойта. Выполните следующие шаги:
/etc/systemd/system/bluetooth.target.wants/bluetooth.serviceExecStart=/usr/libexec/bluetooth/bluetoothd
На следующую :
ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=inputsudo systemctl daemon-reload
sudo systemctl restart bluetoothТеперь вам просто нужно склонировать проект и запустить его, собрав с помощью cargo build или запустив напрямую, указав аргументы следующим образом :
cargo run -- -i [BT_INTERFACE] -t [BT_TARGET].
Снимок 3 : Интерфейс командной строки Rusty Injector.
Вот пример :
cargo run -- -i hci0 -t AA:BB:CC:DD:EE:FF
Ещё одна вещь, которую следует отметить: если вы хотите изменить код и использовать функцию "set_address" через трейт Configuration, вы должны установить инструмент bdaddr для её использования :
# build bdaddr from the bluez source
cd ~/
git clone --depth=1 https://github.com/bluez/bluez.git
gcc -o bdaddr ~/bluez/tools/bdaddr.c ~/bluez/src/oui.c -I ~/bluez -lbluetooth
sudo cp bdaddr /usr/local/bin/
Обратите внимание: если вы не укажете Bluetooth-интерфейс, будет предпринята попытка использовать интерфейс по умолчанию. И ЕСТЕСТВЕННО, не забудьте подключить Bluetooth-адаптер к вашей операционной системе Ubuntu.🙃
Я считаю, что рассказал всё — теперь вы готовы использовать Rusty Injector по полной! Если у вас возникнут какие-либо проблемы, появятся комментарии или отзывы, не стесняйтесь открывать issue. Желаю вам отличного опыта и удачного хакинга! 🚀