Light mode

Пять способов сломать SCADA-систему

  • #Standoff
  • #ThreatHunting

Вся информация предоставлена исключительно в образовательных целях!

На киберполигоне Standoff представлено несколько виртуальных компаний из разных отраслей — каждая со своими бизнес-процессами, серверами, сотрудниками и проблемами. В сегодняшней статье мы рассмотрим атаку на промышленный сектор глазами red team. Я расскажу, как можно остановить производство, имея на руках только IP-адрес сети и несколько email’ов сотрудников. С их помощью мы попробуем добраться до АСУ ТП и реализовать недопустимое событие в компании Metal&Tech!

Путь к АСУ ТП: офис Metal&Tech

Сети всех представленных на киберполигоне компаний разделены на сегменты — ДМЗ и внутреннюю зону. При этом в ДМЗ можно найти информацию для продвижения во внутренний сегмент. Например, злоумышленник может заполучить конфигурации VPN или узнать email’ы пользователей для проведения фишинговой атаки. Кроме того, можно использовать уязвимые веб-серверы, чтобы проникнуть в другой сегмент сети или найти дополнительную информацию для развития атаки. Отмечу, что структуры офисов отличаются, но способы продвижения по ним схожи. В качестве примера рассмотрим атаку на одну из компаний.

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

В первую очередь просматриваем веб-сайты и ищем любую информацию о пользователях, в частности e-mail’ы (как минимум узнаем имя домена и имена пользователей, плюс сможем отправлять письма). Кроме того, проверяем сайты на наличие всевозможных уязвимостей, используя которые, мы сможем получить больше данных. Например, на одном из ресурсов находим уязвимость, которая позволяет выполнять удаленный код. Как результат — получаем конфигурацию подключения по VPN. Кроме того, эта уязвимость открывает нам доступ в ДМЗ, где можно обнаружить дополнительные узлы и сервисы или получить доступ в другой сегмент сети. Обязательно просматриваем DNS-серверы! В результате узнаем структуру ДМЗ и IP-адреса, которые не удалось обнаружить на этапе сканирования.

Другой вектор проникновения в сеть — почтовый сервер. Если в ДМЗ на нем доступен веб-клиент, можно подобрать пароли для найденных email’ов и проверить переписку пользователей на наличие полезной информации. Также имеет смысл поискать на почтовом сервере уязвимости — при успешной эксплуатации мы сразу сможем попасть в серверный сегмент сети. Заполучив учетную запись пользователя, можно от его имени отправлять почту другим сотрудникам. А если добраться еще и до конфигурации VPN, можно попасть в серверный или пользовательский сегмент сети. 

Отмечу, что подбор паролей — довольно «шумная» процедура: шанс успеха невелик, хотя и не исключен. Проще связаться с кем-то из пользователей по электронной почте — отправить ему что-нибудь интересное. Например, HR-специалисты спокойно читают резюме, полученные с неизвестных им адресов. Если на почтовом сервере не реализованы механизмы проверки и фильтрации, а на компьютере получателя отсутствуют СЗИ, есть вероятность, что сотрудник откроет вредоносный документ. При этом на сайте компании обычно есть информация из серии «Если хотите присоединиться к нашей команде — отправьте резюме HR», следом за которой идут email’ы рекрутеров. Отправляем им фишинговые письма с вложенными файлами (документы Word или Excel). Когда один из адресатов откроет файл, мы сможем установить соединение с C2-сервером. 

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

Два кейса

У сети Metal&Tech было две конфигурации: первая прожила два месяца, вторая до сих пор активна. Но мы справились с обеими ;)

Продвижение в первой конфигурации. Попадаем на компьютер сотрудника отдела кадров и собираем информацию о домене. Мы обнаружили у пользователя привилегию, которая позволяет выполнить атаку DCSync на контроллер домена. Далее получаем учетную запись администратора и делаем дамп всех учетных записей в домене. Через GPO создаем задание на установку соединения с C2-сервером и получаем доступ ко всем компьютерам в домене. Остается получить доступ к производственному оборудованию для реализации недопустимых событий. 

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

Продвижение во второй конфигурации. Попадаем на компьютер сотрудника отдела кадров и собираем информацию о домене. Сканируем сеть, узнаем, что у пользователя есть доступ по RDP на сервер BACKUP. Там находим хеши администраторов рабочих станций. Также узнаем, что практически все пользователи домена имеют доступ по RDP на сервер RDG, с которого можно попасть на большинство рабочих станций по тому же RDP. С помощью учетной записи администратора получаем доступ ко всем рабочим станциям в домене, в том числе к устройствам инженеров. Оттуда попадаем в сегмент АСУ ТП и реализуем недопустимые события.

Авария на прокатном стане: разрыв заготовки

Переходим к самому интересному: рассмотрим пять способов реализовать недопустимое событие «Авария на прокатном стане: разрыв заготовки». А в качестве бонуса захватим еще и «Остановку прокатного стана». 

Обычно компьютеры операторов АСУ ТП не входят в состав домена, поэтому использовать доменные учетные записи здесь не получится — искать нужный пароль придется где-то еще. Пароли операторов АСУ ТП, как и других пользователей домена, могут лежать где угодно: в базах со слабыми паролями (например, KeePass), в браузерах, на веб-серверах, в текстовых файлах, даже в коде приложений или скриптов. Проверяем компьютер оператора на наличие уязвимостей и, если удастся что-то обнаружить, эксплуатируем. В итоге получаем заветный пароль и подключаемся к ПК по RDP.

Далее собираем необходимую информацию: установленное ПО SCADA — WinCC OA 3.18, расположение папки с проектом — C:\WinCC_OA_Proj\RM и используемый PLC-контроллер — Omron CS1G_CPU43H. Пароля от самого ПО SCADA у нас нет, поэтому пока пройти аутентификацию не получится.

Затем анализируем содержимое папки с проектом. Находим несколько панелей в директории panels: нас интересуют MainPanel.pnl (основной интерфейс операторской системы) и Login.pnl (форма аутентификации). Login.pnl зашифрована паролем, поэтому мы не можем посмотреть ее содержимое, но для решения нашей задачи она не понадобится. В свою очередь, MainPanel.pnl не зашифрована и представляет собой текстовый файл, в котором описаны графические элементы и функции панели. Далее анализируем «WinCC OA 3.18 Консоль» и видим несколько запущенных процессов (в том числе «Интерфейс пользователя» с панелью MainPanel.pnl) и скрипты.

Изучив содержимое MainPanel.pnl, находим элемент «Cage_T_3». При его изменении тегу, относящемуся к PLC-контроллеру, присваивается новое значение. То что нужно!

"Cage_T_3"

...

0 "Change" "(int value)"

"  dpSetWait(\"PLC_Signal.Set_Cage_T_3\",value);"

Осталось понять, как изменить значение «Cage_T_3» с наименьшими правками в проекте. Немного поразмыслив, почитав документацию и изучив активные скрипты, я решил написать свой. Разобрался в логике, поигрался с некритическими значениями, и решение нашлось. Если установить значение элемента «Cage_T_3» от 0 до 10, мы сможем реализовать недопустимое событие. Задача ясна, поехали!

Пять способов реализовать недопустимое событие

Способ первый: «Быстро и со вкусом»

В папке C:\WinCC_OA_Proj\RM\scripts создаем новый скрипт с любым именем. Добавляем в скрипт команду, найденную в MainPanel.pnl, а вместо переменной value задаем нужное нам значение. В «WinCC OA 3.18 Консоль» добавляем новый менеджер сценариев. В «Опции» вводим имя созданного скрипта и выбираем режим запуска «вручную». В консоли выбираем и запускаем созданный нами менеджер сценариев. 

Недопустимое событие реализовано! Как я уже упоминал, в этом способе мы не вносим никаких изменений в файлы проекта и не останавливаем его.

Способ второй: «Что истина, а что ложь»

Перед нами все-таки стояла задача пройти аутентификацию либо как-то ее обойти. Еще раз внимательно изучаем MainPanel.pnl и находим функцию CheckLogin. В ней видим условие: если длина имени пользователя не равна нулю, активируются элементы, значения которых можно изменять. Значит, нам нужно изменить условие так, чтобы всегда возвращалось значение true. Здесь полет фантазии неограничен. Останавливаем проект, изменяем условие в панели, снова запускаем и видим, что все неактивные элементы стали активными. Меняем значение Thickness в Cage 3 — цель достигнута!

Способ третий: «I am root!»

Предыдущие два способа сработали только потому, что MainPanel.pnl не была зашифрована (в отличие от Login.pnl). В противном случае мы бы не смогли внести изменения в панель или получить нужный тег PLC-контроллера, чтобы выполнить скрипт. Значит, нужно найти способ пройти аутентификацию, а для этого необходим пароль оператора, которого у нас нет. Здесь на ум приходит только одно: попробуем сменить пароль пользователя.

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

В документации к WinCC OA сказано, что через команду dpSet() нельзя изменять значения в точке данных _Users (из соображений безопасности). Поэтому мы пойдем другим путем. Обычно учетные данные пользователей хранятся в БД. В папке с проектом есть директория db — исследуем ее и находим в одном из файлов пользователей хеши, полученные на первом шаге.

Генерируем новый хеш с известным нам паролем. Останавливаем проект и делаем копию файла с найденными учетными записями на случай, если что-то пойдет не так. Меняем текущий хеш от пользователя root на только что созданный. Запускаем проект, нажимаем кнопку Login, вводим «root» в поле User и «password» (то есть наш пароль) в поле Password. Если все сделано верно, мы успешно проходим аутентификацию и меняем значение Thickness в Cage 3.

Теперь у нас есть учетная запись привилегированного пользователя root и мы можем получить доступ в интерфейсы gedi и para. Открываем «WinCC OA 3.18 Консоль», запускаем интерфейс пользователя («-m gedi -user root») и вводим наш пароль. Таким образом получаем полный доступ к проекту. Кроме того, через модуль para можно изменить значение тега PLC_Signal.Set_Cage_T_3 и тем самым реализовать недопустимое событие.

Способ четвертый: «MasterOPC — защита от дурака»

В предыдущих способах мы взаимодействовали с WinCC OA, а в последних двух воспользуемся PLC-контроллером.

Еще раз осмотрев установленное на машине ПО, находим Multi-Protocol MasterOPC Server, который отвечает за связь с PLC-контроллером. Запускаем конфигуратор и видим, что для редактирования нужен пароль, которого у нас нет. Находим файл с рабочей конфигурацией C:\ProgramData\InSAT\Multi-Protocol MasterOPC Server\SERVERCFG\omron.mpp и еще несколько аналогичных примеров.

Файлы конфигураций — это обычные ZIP-архивы. В архиве omron.mpp есть несколько файлов, в одном из которых хранятся основные настройки. Раз содержимое файлов легко читается при наличии парольной защиты, логично предположить, что пароль находится в одном из параметров. Чтобы понять, где он хранится, проведем небольшой анализ: берем любой файл из примеров, делаем его копию, ставим пароль и сравниваем с оригиналом. Видим, что в файле с настройками изменилось значение одного параметра. Соответственно, значение этого параметра в незапароленном файле и является значением пустого пароля. Заменяем соответствующие значения в omron.mpp, перезапускаем конфигуратор и получаем доступ к редактированию настроек.

Далее видим все настроенные теги, в том числе и нужный нам set_Cage_T_3 (уровень доступа ReadWrite). Меняем его значение и в очередной раз реализуем недопустимое событие!

Способ пятый: «Можно и через командную строку все сломать»

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

Забираем файл omron.mpp и извлекаем из него нужные данные. Получаем настройки подключения к PLC-контроллеру, определяем его IP-адрес (10.154.1.38) и порт UDP (9600). Видим, что аутентификации там нет.

На PLC-контроллер можно посылать сырые данные: аналогично тому, как это делает MasterOPC Server. Чтобы определить, что отправлять контроллеру, можно почитать документацию или перехватить дамп трафика. Но проще локально установить Multi-Protocol MasterOPC Server, добавить конфигурацию omron.mpp, изменить IP-адрес, запустить прослушивание на порте 9600 и получить данные, которые обычно посылаются PLC-контроллеру.

После этого пишем небольшой скрипт на Python. Устанавливаем сам Python, запускаем скрипт и снова реализуем недопустимое событие!

В качестве бонуса рассмотрим реализацию еще одного недопустимого события — «Остановку прокатного стана». 

Отсматриваем теги и пробуем все возможные способы, но ничего не находим. На помощь приходит интернет: на exploit-db видим POC, в котором есть код, позволяющий остановить PLC-контроллер. Для нашего контроллера POC не подходит, но если мы изучим его подробнее и почитаем документацию, то быстро поймем, что нужно исправить. Во время реализации пятого способа мы получили все необходимые данные — остается только их скорректировать. Редактируем скрипт, запускаем его и полностью останавливаем контроллер. 

Второе недопустимое событие реализовано!

Мы дěлаем Positive Research → для ИБ-экспертов, бизнеса и всех, кто интересуется ✽ {кибербезопасностью}