Уязвимости и вредоносный код в системах промышленной автоматизации

Разработанные 15–20 лет назад средства промышленной автоматизации практически не содержали функций обеспечения безопасности. За прошедшие десятилетия на предприятиях накопился целый парк оборудования с неустранимыми архитектурными недостатками, доступными для эксплуатации киберпреступниками. В этом посте рассказываем об уязвимостях промышленных систем автоматизации и приводим рекомендации по улучшению ситуации.

image
В 2019 году мы обнаружили в интернете магазин, распространяющий программное обеспечение для тяжёлых промышленных машин. Мы скачали некоторые из этих приложений и провели их реверс-инжиниринг, чтобы понять, как они работают. Их код был написан на одном из проприетарных языков программирования, использовавшихся для автоматизации промышленных роботов, которые собирают автомобили и упаковывают пищевые продукты на конвейерах. В одном из этих приложений обнаружилась уязвимость, с которой и началось наше исследование Rogue Automation: Vulnerable and Malicious Code in Industrial Programming.

Изучив технические детали и слабые места восьми наиболее популярных сред промышленного программирования (ABB, Comau, Denso, Fanuc, Kawasaki, Kuka, Mitsubishi и Universal Robots), мы выяснили, что эти языки можно использовать для создания вредоносов-червей, которые будут перемещаться с одного уязвимого робота на другой, подчиняясь дистанционным командам своих операторов.

Обнаруженные недостатки — результат выбора дизайна, созданного несколько десятилетий назад. Эти решения определили технологию, методы и инструменты, которые до сих пор используются для программирования промышленного оборудования. Рассмотрим последствия такого выбора в контексте современных киберугроз.

Кража данных у робота


Мы обнаружили реальный случай уязвимого веб-сервера, реализованного в виде приложения для запуска на промышленном роботе. Веб-сервер, написанный на языке ABB Rapid, содержал уязвимость обхода путей, которая позволяла злоумышленнику подключиться к роботу по сети и копировать любые файлы с контроллера робота, включая журналы работы. Такие файлы с большой вероятностью содержат различные конфиденциальные данные и ноу-хау, поэтому их можно выгодно реализовать на подпольных рынках.

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

image
Фрагмент кода уязвимого приложения. Источник (здесь и далее, если не указано иное): Trend Micro

В строке 493 вызывается функция sendFile для отправки запрошенного файла клиенту. Строка pageString никак не фильтруется, поэтому может содержать »…/» или другой путь. Это позволяет выполнить обход файловой системы и скачать практически любой файл.

image
Схема эксплуатации уязвимости

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

image
Фрагмент кода с комментарием разработчика о том, что санитизацию данных должен выполнять браузер

Подмена команд роботу по сети


Эксплуатация некоторых уязвимостей может привести к последствиям в физическом мире, например, причинить вред готовым изделиям или даже окружающим людям.
В open-source проекте для промышленных роботов Kuka мы обнаружили уязвимость, которая позволяет изменить траекторию движения подвижной части. Программа получает поток координат по сети и передаёт их исполнительному механизму, который выполняет заданные перемещения. Для этого используется специальный класс процедур — серверы автоматизации движения. Это стандартный интерфейс, который позволяет OEM-производителям промышленных роботов обеспечить единый способ управления перемещением их изделий.

image
Уязвимый код сервера автоматизации движения не содержит никаких проверок на легитимность переданных ему данных

Код сервера никак не проверяет, откуда поступила очередная порция координат для перемещения робота, в нём не предусмотрена внутренняя аутентификация. Единственной защитой является проверка MAC-адреса и IP-адреса отправителя, любой из которых может быть с лёгкостью подделан проникшим в сеть злоумышленником.

На нашем лабораторном стенде мы убедились, что, используя спуфинг, можно фальсифицировать трафик между роботом и инженерной рабочей станцией. Злоумышленник мог посылать произвольные координаты, а робот просто выполнял их, что на реальном производстве привело бы к несчастному случаю.

Внедряя в трафик сетевые пакеты с неверными координатами, мы смогли несколько раз вытолкнуть манипулятор за пределы зоны безопасности и ударить «рукой» робота по физическому объекту. В результате «рука», с помощью которой робот подбирает объекты, отвалилась:

image
Отвалившаяся рука робота — результат внедрения небезопасных координат в трафик

Динамические вредоносы


Эта разновидность атаки предполагает, что робот работает под управлением программы, написанной системным интегратором, которая считается доверенной. В реальности любая созданная интегратором программа считается доверенной и разворачивается без проверок кода на безопасность.

Скомпрометировав интегратора или заменив программу в уязвимом сетевом хранилище, можно незаметно внедрить в сеть предприятия вредоносный код: добавить загрузчик, который скачивает нужный злоумышленнику модуль и запускает его на выполнение как часть стандартного производственного цикла.

image
Загрузчик вредоноса, написанный на языке программирования для промышленных роботов

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

Необычная RCE-уязвимость


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

image
Уязвимая логика работы «добропорядочного» приложения

image
Фрагмент кода, реализующий уязвимую логику.

Хотя сама по себе программа не содержит вредоносных функций, злоумышленник может воспользоваться ей, чтобы отдавать команды роботу в нужный ему момент, оказывая влияние на физический мир.

Венец творения — червь-вредонос


Для демонстрации серьёзности обнаруженных проблем мы разработали программу с функцией саморазмножения и автоматического обновления, динамической загрузкой кода с управляющего сервера и возможностью удалённого управления. Проверочная программа также может выполнять сетевое сканирование, передавать на управляющий сервер произвольные файлы, вести список заражённых устройств и выполнять функции бота.

image
Логика работы PoC-программы, имитирующей работу реального вредоноса

image
Формирование списка найденных файлов и его отправка на управляющий сервер

Источник проблем


Проанализировав восемь популярных языков программирования для промышленной автоматизации, разработанных в прошлые десятилетия, мы пришли к выводу, что основная причина выявленных и потенциальных уязвимостей состоит в том, что эти языки содержат низкоуровневые средства для доступа к системным ресурсам. И хотя эти средства сами по себе не являются чем-то опасным, злоумышленники могут использовать их не по прямому назначению, критически повлияв на безопасность робота, его оператора и подключённых систем. Например, с их помощью можно перемещать манипулятор вверх, поднимать заготовку, опускать манипулятор вниз и освобождать заготовку.

Этот богатый набор сложных функций даёт инженерам-технологам свободу при разработке прикладных программ, в которых они могут получать данные из сети читать и записывать файлы. Однако, поскольку платформы не реализуют защищённый доступ к этим расширенным возможностям, злоумышленники могут использовать их для написания вредоносных модулей.
Другая проблема устаревших языков для промышленной автоматизации (Industrial Robots Programming Language, IRPL), доставшихся в наследство вместе с оборудованием, состоит в том, что для них не существует средств проверки кода на небезопасные паттерны, подобных инструментарию для C, C++, C#, Java, PHP и Python.

Каждый OEM-производитель создаёт свои собственные языки и среду, в которой будут выполняться целевые программы. Некоторые из них основаны на операционных системах реального времени (RTOS), но в целом стандартизации не существует. Семантика каждого IRPL также уникальна и может существенно отличаться от семантики языков программирования общего назначения. Некоторые возможности, например, для манипулирования строками или криптографических операций, в IRPL либо отсутствуют, либо не настолько развиты, как в традиционных языках.

Главные источники уязвимостей в программах, написанных на IRPL, —три основные функции:

  • работа с файлами и каталогами,
  • динамическая загрузка модулей и вызов функций по имени,
  • сетевые функции — приём и передача данных внешним системам.


image
Доступные в IRPL «опасные» функции

Как защититься


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

image
Сводные рекомендации по обеспечению безопасности программ для промышленной автоматизации

Следовательно, при написании таких программ необходимо руководствоваться следующими принципами:

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


Старые или умные?


В то время, как разработчики традиционного ПО десятки лет сражаются с последствиями небезопасного программирования и вырабатывают различные методики, обеспечивающие победу, мир промышленной автоматизации оказался неподготовленным к обнаружению и предотвращению эксплуатации уязвимостей.

Учитывая темпы конвергенции IT/OT, необходимо в приоритетном порядке внедрять в индустрию промышленной автоматизации методы разработки безопасного кода. В противном случае ближайшие несколько лет могут принести нам множество сообщений об инцидентах в сфере промышленности, причём последствия этих инцидентов будут проявляться не только в киберпространстве, но и в физическом мире.

© Habrahabr.ru