
Коллекция уязвимостей и эксплойтов против современных GCS
Векторы атак, уязвимости и эксплойты «дрон — наземная станция управления»
Сегодня флот дронов — это один оператор, управляющий десятками или сотнями дронов с единственной наземной станции. Это делает наземную станцию управления ценной целью для противников. Именно там обычно находится пилот, там часто хранятся данные миссий, и это — основной вектор для бокового перемещения по сетям UxS и другим дронам во флоте.
Большинство исследований по безопасности дронов было сосредоточено на атаке на сам дрон. Исследование Infected Drone использует альтернативный подход и показывает, как один скомпрометированный дрон может атаковать наземные станции, которые к нему подключаются. Поскольку большинство программ наземного управления доверяет всему, что присылает дрон, отсутствуют аутентификация, валидация и санитизация, что позволяет данным от скомпрометированного дрона приводить к CRUD-операциям с файлами, выполнению кода или краху на машине оператора.
Этот репозиторий документирует уязвимости в программном обеспечении наземных станций управления и поставляет рабочий proof-of-concept код для них. Он опубликован исключительно в образовательных целях и для того, чтобы операторы понимали свою подверженность риску, а мейнтейнеры могли воспроизвести и исправить эти проблемы.
Запускайте PoC только против систем, которыми вы владеете или на тестирование которых у вас есть письменное разрешение. Каждый из них написан для стенда: полезные нагрузки — это безобидные маркеры, и ничто здесь не упаковано для использования против чужого воздушного судна или наземной станции. Использование этого материала против систем, которые вы не контролируете, скорее всего незаконно, где бы вы ни находились.
Раздел «Reproduction» для каждой находки указывает, что ей нужно и что она делает. Прочитайте его, прежде чем запускать что-либо.
Легенда:
Класс доставки — это то, что атакующий должен сделать на канале, и он определяет, какие векторы работают. Находкам типа Push достаточно лишь кадра, прибывающего на GCS, поэтому достаточно любого вектора, способного к инъекции. Находки типа Handshake и request/response требуют, чтобы атакующий был или полностью контролировал собеседника в диалоге, что благоприятствует периферии на шине, скомпрометированному компаньону, цепочке поставок или полному MITM.
Столбец Fix ссылается на upstream pull request, если он был отправлен. Десять из пятнадцати находок поставляются с патчем, отправленным в собственный репозиторий вендора.
Матрица оценивает семь столбцов на каждую находку: пять векторов ниже, плюс два режима SiK-радио (RF-телеметрия), которым ниже посвящён отдельный раздел с учётом нюанса инъекция-против-MITM.
Заражённый полётный контроллер, последовательное подключение или цепочка поставок. Локальный атакующий или вредоносный полётный контроллер физически подключается к хосту GCS или радио. Аппарат или прошивка — это то, что оператор не собирал: демо-экземпляр, аренда, изъятый корпус или подержанный аппарат, в прошивку которого имплантировано испускание враждебного MAVLink в момент подключения GCS. Собственная GCS оператора — жертва; «аппарат» был враждебным ещё до того, как его вообще включили. Применимо к каждой находке и является самым чистым способом доставки эксплойтов connect-time handshake. Это распространяется и на криминалистов, которые могут подключаться напрямую к заражённому аппарату или извлекать из него данные. Эти артефакты, если с ними не обращаться должным образом, могут заразить или распространиться на компьютер и сеть аналитика.
Вредоносная / поддельная периферия MAVLink на собственной шине аппарата. Сторонняя камера, подвес, ADSB-in, дальномер или любое устройство, которое говорит на MAVLink и само является атакующим. Это легитимный участник на канале, испускающий враждебные кадры. Поддельная «умная камера», рекламирующая отравленные сообщения, делает ровно то же, что и настоящая, только с враждебными значениями.
Скомпрометированный бортовой companion-компьютер (Raspberry Pi / Jetson с mavlink-router / MAVProxy). После компрометации он становится конечной точкой аппарата, с полным двунаправленным доступом к каналу и видимостью его живого состояния. Он может ответить на любой handshake и испустить любой push-кадр, что делает его пригодным для каждой находки в этом наборе.
WiFi / UDP мост телеметрии (ESP8266 / ESP32 «wifi telemetry»). Любой в точке доступа или LAN может инжектировать данные MAVLink. Это сводит стоимость векторов инъекции к почти нулю и, для атакующего, который также может перехватывать (ARP/AP MITM), включает и полный контроль над handshake.
TCP / облачный релей (SITL, mavlink-router TCP, mavp2p, 4G/LTE облачная GCS, такая как коммерческие UAV-cloud сервисы). MITM на релее или любой, кто может достичь открытого TCP-порта, может перезаписывать поток. Облачные/4G-каналы расширяют географический радиус поражения колоссально и часто не имеют взаимной аутентификации.
Доминирующий путь реальной RF-телеметрии для любительских и prosumer-аппаратов ArduPilot/PX4 — это пара SiK-радио, прозрачный последовательный мост, который не парсит и не валидирует MAVLink, поэтому он не даёт GCS никакой защиты от враждебного контента. Вредоносный SiK-модуль присоединяется к существующему каналу или становится мостом в нём, используя sikw00f. Два режима атаки с очень разной надёжностью:
STATUSTEXT, PARAM_VALUE,
CAMERA_INFORMATION и т. д.), ответ не нужен. Ненадёжно для handshake-протоколов
(MAVFTP, скачивание параметров/логов), поскольку инжектор должен выиграть гонку за эфирное
время и совпасть с session/sequence, которым он не управляет.Примечание: шифрование SiK (AES-128, где поддерживается) поставляется выключенным по умолчанию со статическим общим ключом.
| ID | Продукт | Sev | CWE | Класс стока | Класс доставки | Infected FC / цепочка поставок? | Вредоносная периферия на шине? | Скомпрометированный компаньон? | WiFi/UDP инъекция? | TCP/облачный MITM? | Инъекция SiKW00F? | SiK полный-MITM? | Fix |
|---|
| QGC-01 | QGroundControl | 🟠 HIGH | 22/73/170 | CAMERA_INFORMATION → запись через path-traversal (zero-click запись при подключении) | push (CAMERA_INFORMATION) + контент через cam_definition_uri | ✅ | ✅ наиболее естественно (камера) | ✅ | ✅ | ✅ | ✅ триггер — push; поля имени инлайн | ✅ | PR #15083 |
| QGC-02 | QGroundControl | 🔴 CRITICAL | 22/73/494/918 | COMPONENT_METADATA uri → произвольная запись файла → zero-click RCE при подключении | request/response (URI fetch по IP) | ✅ | ✅ испускает metadata uri | ✅ | ✅ для триггера | ✅ | ⚠️ push-триггер да; fetch идёт по IP | ✅ | PR #15084 |
| QGC-03 | QGroundControl | 🟠 HIGH | 22/770 | FTP listing → запись через traversal + заполнение диска через offset | handshake (MAVFTP listing/download) | ✅ | ✅ пир отвечает по FTP | ✅ | ⚠️ инъекция да, собственный handshake сложнее | ✅ | ⚠️ гонки session/seq | ✅ мост отдаёт listing | PR #15085 |
| QGC-04 | QGroundControl | 🟡 MED | 191/125 | Парсер DataFlash .bin OOB read + underflow | handshake (скачивание лога вредоносного .bin) | ✅ | ✅ пир отдаёт DataFlash | ✅ | ⚠️ | ✅ | ⚠️ должен отдавать чанки лога | ✅ мост подаёт .bin | PR #15086 |
| MP-01 | Mission Planner | 🟠 HIGH | 22→94 | MAVFTP traversal → RCE через загрузчик плагинов | handshake (MAVFTP req/ack → RCE) | ✅ | ✅ пир отвечает на listing | ✅ полный контроль канала | ⚠️ инъекция проста, но нужно владеть handshake | ✅ перезапись на релее | ⚠️ нужно выиграть гонку + совпасть session/seq | ✅ мост владеет FTP-диалогом | PR #3774 |
| MP-02 | Mission Planner | 🟠 HIGH | 94/78 | gst:// → gst_parse_launch (чтение/запись файлов + эксфильтрация) | push (VIDEO_STREAM_INFORMATION → gst) | ✅ | ✅ камера объявляет uri | ✅ | ✅ UDP-датаграмма | ✅ | ✅ одноразовый кадр потока | ✅ тривиально | PR #3775 |
| MP-03 | Mission Planner | 🟠 HIGH | 74/601 | Разметка STATUSTEXT → Process.Start | push (STATUSTEXT → ShellExecute) | ✅ | ✅ любой компонент испускает | ✅ | ✅ | ✅ | ✅ текст fire-and-forget | ✅ | PR #3776 |
| MP-04 | Mission Planner | 🟡 MED | 248/20/1050 | RALLY_TOTAL/FENCE_TOTAL → невалидированный int.Parse + O(n²) в UI-потоке (zero-click при подключении) | push (PARAM_VALUE, авто после подключения) | ✅ | ✅ испускает PARAM_VALUE | ✅ | ✅ | ✅ | ⚠️ нужно, чтобы параметр попал в dict MP | ✅ | PR #3777 |
| MAVSDK-01 | MAVSDK | 🟡 MED | 918/749 | curl SSRF через component-metadata + file:// (нет allowlist протоколов) | request/response (fetch COMPONENT_METADATA.uri по IP) | ✅ | ✅ испускает metadata uri | ✅ | ✅ для триггера | ✅ | ⚠️ push-триггер да; fetch по IP | ✅ | нет |
| MAVSDK-02 | MAVSDK | 🟠 HIGH | 22/73/918 | SSRF через cam-definition + traversal mftp:// → zero-click уничтожение файла вне песочницы | push (CAMERA_INFORMATION.cam_definition_uri, авто) | ✅ | ✅ наиболее естественно (камера) | ✅ | ✅ | ✅ | ✅ автоматически потребляемый push | ✅ | PR #3073 |
| MAVSDK-03 | MAVSDK | 🟠 HIGH | 409/400/770/459 | .xz cam-definition или COMPONENT_METADATA → неограниченная декомпрессия → устойчивое исчерпание диска | push (CAMERA_INFORMATION.cam_definition_uri, авто) — запускается от простого HEARTBEAT | ✅ | ✅ наиболее естественно (камера) | ✅ | ✅ | ✅ | ✅ автоматически потребляемый push; ~50 с эфирного времени на 57.6 кбит/с на каждые 2 ГиБ | ✅ | PR #3074 |
| MAVPROXY-01 | MAVProxy | 🟠 HIGH | 502 | asterix pickle.loads по UDP → RCE | IP-сайд-канал (UDP, НЕ радио-канал MAVLink) | ❌ не на канале MAVLink | ❌ отдельный UDP-сокет | ⚠️ только если может достичь :45454 | ✅ UDP на host:45454 | ❌ собственный UDP-сокет, не релей | ❌ не на радио/MAVLink канале | ❌ не на радио/MAVLink канале | исправлено upstream через #1728, не выпущено |
| MAVROS-01 | mavros | 🟡 MED | 345/770 | PARAM_VALUE → подделка глобального /parameter_events + неограниченная map | push/stream (инъекция PARAM_VALUE, без handshake) | ✅ | ✅ испускает PARAM_VALUE | ✅ | ✅ UDP-флуд | ✅ | ✅ флуд PARAM_VALUE | ✅ | нет |
| MAVROS-02 | mavros | 🟠 HIGH | 125/617/248 | FTP write-ack → неограниченный std::advance → раскрытие кучи + аварийное завершение процесса | handshake (отравленный FTP-ответ → крах) | ✅ | ✅ пир отправляет плохой FTP | ✅ | ⚠️ | ✅ | ⚠️ нужно доставить некорректный ответ | ✅ мост инжектирует плохой ответ | нет |
| DRONEKIT-01 | DroneKit | ⚪ INFO | 20 | передача через границу доверия (param_id / STATUSTEXT) | push (телеметрия → колбэки приложения; передача by-design) | ✅ | ✅ любой компонент | ✅ | ✅ | ✅ | ✅ любой push-кадр достигает колбэка | ✅ | н/д |