Статья Уязвимости промышленных протоколов связи: фундаментальное исследование Modbus TCP и BACnet/IP

1769977785308.webp


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

Мы живём в мире, где физическая реальность - поворот клапана, нагрев печи, движение конвейера - управляется битами и байтами. И связующим звеном между цифровой командой и физическим действием уже несколько десятилетий выступают не какие-то навороченные API с OAuth и blockchain, а древние, как мамонтовая кость, промышленные протоколы. Они создавались в эпоху, когда «сеть» означало отрезок кабеля между двумя шкафами в одном цеху, а слово «хакер» если и употреблялось, то в контексте MIT и беззлобных шалостей. Они создавались с верой в добропорядочность и компетентность окружающих, с приоритетом на надёжность, простоту отладки и долгосрочную работу без сбоев. Безопасность в её современном, параноидальном понимании, просто не была в списке требований.

И вот эти цифровые динозавры - Modbus, BACnet, PROFINET, EtherNet/IP - оказались вшиты в плоть и кровь критической инфраструктуры: энергетики, водоснабжения, нефтегаза, транспортных систем, умных зданий. Они молчаливо работают годами, выполняя свою функцию, пока однажды не оказывается, что к этому архаичному, но критически важному слою технологического стека приложили палец извне. Не палец - клавиатуру. И вся хрупкость конструкции, основанной на доверии и изоляции, выходит на первый план.

Кибербезопасность зациклена на IT-мире: атаки на веб-сервера, утечки баз данных, криптолокеры для Windows-станций. Это важно, но это лишь верхний слой. Когда они говорят про атаки на заводы, они либо впадают в панику и рисуют образ апокалипсиса, либо, что хуже, поверхностно тычут в «ошибки безопасности», не понимая корня. Они говорят на языке уязвимостей (CVE), эксплойтов, троянов. Но в мире Operational Technology (OT) часто не нужен ни троян, ни zero-day. Нужно понимание.

Понимание того, что:
  • Стандартный пароль - это не «admin123», а часто его полное отсутствие. Протокол может просто не иметь такого поля в пакете.
  • Шифрование - это не AES-256, а plain-text, где каждая команда «включить насос» видна как на ладони любому снифферу в сети.
  • Аутентификация - это не сертификат или токен, а IP-адрес отправителя (который можно подделать) или просто факт наличия соединения.
  • Сетевая сегментация - это не микросегментация с next-gen фаерволами, а мифический air-gap (воздушный зазор), который давно «преодолён» для удобства удалённого доступа или передачи данных в ERP-систему.
Этот мир живёт по парадигме «Stability over Security». Перезагрузка контроллера для установки патча? Это плановая остановка производства, согласованная за месяц, с потерей сотен тысяч. Обновление прошивки? Риск, что новое ПО не будет работать со старыми датчиками, купленными 15 лет назад и уже не выпускаемыми. Здесь железо и софт покупаются на десятилетия. Windows XP? Да это молодость! Здесь могут быть системы на QNX, VxWorks или вообще кастомные ОС реального времени, о которых нет информации в интернете.

Если ты читаешь это, ты, вероятно, либо любопытный исследователь, либо уставший админ, которого бросили «разбираться ещё и с этими железяками», либо инженер АСУ ТП, втайне подозревающий, что с его сетью что-то не так. Этот материал - для тебя.

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

Но доверие - не стратегия. И наша задача - без паники, без обвинений, с честностью разобрать, как устроены эти протоколы-динозавры, где в них бреши, и - что самое главное - как это выглядит на практике. Мы уйдём от абстрактных «киберугроз» к конкретным hex-дамперам, структурам пакетов, Python-скриптам в несколько строк и командам в терминале.

Здесь будет:
  1. Глубокий дайв в философию и историю протоколов Modbus и BACnet. Не просто сухие факты, а контекст, который объясняет их уязвимости.
  2. Детальный технический разбор структур данных, полей пакетов, кодов функций - с примерами и hex-кодом.
  3. Практические инструменты - от готовых скриптов и утилит до методик ручного анализа с помощью netcat и Wireshark. Мы покажем не только «как сканировать», но и «как интерпретировать» сырые данные.
  4. Сценарии эксплуатации в лаборатории - пошаговые инструкции для построения стенда и безопасного тестирования, потому что понимание приходит только через руки.
  5. Стратегии защиты не из учебников, а приземлённые, основанные на понимании ограничений OT-среды. Не «надо всё зашифровать», а «как максимально усилить оборону, когда полное шифрование невозможно».


Часть 1: Философия тишины. Почему OT - не IT, и в этом вся проблема.

Прежде чем лезть в байты и фреймы, надо понять среду. Operational Technology (OT) - это не просто ещё одна сеть в компании. Это параллельная вселенная, живущая по своим, часто архаичным, законам.

Контраст IT-безопасности:
В IT-мире царит паранойя (часто оправданная). Межсетевые экраны, IDS/IPS, EDR, сложная аутентификация, регулярные патчи, принцип наименьших привилегий. Это мир постоянной гонки вооружений, где атака и защита итеративно улучшаются.

OT - мир стабильности и непрерывности. Здесь главный бог - Uptime (время безотказной работы). Перезагрузить сервер? Просто так? Чтобы поставить патч, который, не дай бог, сломает совместимость с софтом для управления турбиной 1998 года выпуска? Да ты шутишь! Здесь системы работают годами, десятилетиями. Апдейт - это плановая остановка производства, миллионы убытков, согласования с десятком инженеров. Поэтому здесь до сих пор можно встретить Windows NT, Windows XP (часто без SP), а то и вовсе специализированные ОС реального времени (RTOS), о которых слыхали лишь единицы.

Сетевая архитектура? Принцип «air gap» - воздушной прослойки. Мол, если нет физического подключения к интернету, то и атаковать нечего. Святая вера в изоляцию. Но реальность такова: этот «gap» давно стал мифом. Данные для отчётов всё равно нужно передавать в корпоративную сеть. Удалённый доступ для техподдержки вендора - must have. Инженер принёс заражённую флешку с новой прошивкой. И вот уже сегмент OT, который должен быть священным и неприкосновенным, оказывается связан с IT-сетью через какой-нибудь хлипкий файрвол с правилом «ANY-ANY», потому что «ну оно же не работает иначе!».

Понимание инженеров OT:
Не стоит их винить. Их KPI - это не отражённые атаки, а тонны продукции, градусы температуры, литры в секунду. Их инструменты - SCADA/HMI системы. Их язык - не Python и не ассемблер, а функциональные блок-схемы, лестничные диаграммы (Ladder Logic). Для них сеть - это просто транспорт для данных между контроллером (ПЛК - Программируемый Логический Контроллер) и операторской станцией. Безопасность? Часто это физический замок на шкафу с оборудованием. И их можно понять. Когда твоя задача - не дать взорваться котлу, мысли о фаззинге Modbus TCP кажутся оторванными от реальности.

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


Часть 2: Modbus. Дедушка, который всё ещё в строю и открыт нараспашку.

Историческая справка (без скуки):
Представь 1979 год. Диско, «Звёздные войны», персональные компьютеры - это экзотика. А компания Modicon (позже купленная Schneider Electric) выпускает первую ПЛК-систему и протокол для общения с ней по последовательной линии (RS-232/485). Назвали Modbus. Философия проста: «мастер» (клиент, например SCADA) опрашивает «слейвов» (серверов, ПЛК), запрашивая или записывая данные в их внутреннюю память. Никакой аутентификации. Никакой сессионности. Всё строится на запросе-ответе. Это был гениальный для своего времени KISS-принцип (Keep It Simple, Stupid). И он завоевал мир. С появлением Ethernet протокол переехал в TCP (порт 502) - Modbus TCP, сохранив свою простоту.

Как это работает (на пальцах и в hex):
Всё вращается вокруг четырёх типов данных, которые хранятся в ПЛК:
  1. Coils (Кайлы, Дискретные выходы) - биты, которые можно читать и писать. Включить/выключить насос, открыть/закрыть задвижку. Адресация: 00001-09999.
  2. Discrete Inputs (Дискретные входы) - биты, которые можно только читать. Датчик конца хода, сигнал «авария». 10001-19999.
  3. Holding Registers (Регистры хранения) - слова (16 бит), которые можно читать и писывать. Уставки температуры, таймеры, счётчики. 40001-49999.
  4. Input Registers (Регистры входов) - слова (16 бит), только для чтения. Текущая температура, давление, расход. 30001-39999.
Важно: это логическая адресация. Реальный адрес в памяти ПЛК вычисляется путём вычитания смещения. Например, запрос к регистру 40014 в пакете будет означать логический адрес 13 (т.к. отсчёт часто с 0).

Структура фрейма Modbus TCP (проще пареной репы):
Пакет - это надстройка Modbus Application Protocol (MBAP) + сам PDU (Protocol Data Unit) запроса/ответа.

MBAP Header (7 байт):
  • Transaction Identifier (2 байта): Чтобы сопоставить запрос и ответ. Для атаки часто 0x0000.
  • Protocol Identifier (2 байта): Всегда 0x0000 для Modbus.
  • Length (2 байта): Длина оставшейся части (PDU + Unit Identifier).
  • Unit Identifier (1 байт): Аналог slave ID в Modbus RTU (последовательном). В TCP часто игнорируется или используется для маршрутизации к конкретному устройству в шлюзе. Часто 0xFF или 0x01.
PDU (запроса):
  • Function Code (1 байт): Суть команды. Ключевые для нас:
    • 0x01: Read Coils
    • 0x02: Read Discrete Inputs
    • 0x03: Read Holding Registers <- Хлеб и масло атакующего
    • 0x04: Read Input Registers <- Тоже очень важно
    • 0x05: Write Single Coil <- Включить/выключить что-то одним пакетом
    • 0x06: Write Single Register
    • 0x0F: Write Multiple Coils
    • 0x10: Write Multiple Registers <- Мощное оружие
  • Data: Адрес начала и количество данных.
Пример «разведки боем» вручную (с помощью netcat):
Допустим, мы нашли хост с открытым портом 502. Хотим прочитать первые 10 holding registers (адреса 40001-40010).
  1. Строим MBAP заголовок: 00 00 00 00 00 06 FF
    • Transaction ID: 00 00
    • Protocol ID: 00 00
    • Length: 00 06 (шесть байт дальше: 1 байт Unit ID + 5 байт PDU)
    • Unit ID: FF (255, «broadcast»-подобный, но многие устройства ответят)
  2. Строим PDU для чтения регистров (функция 0x03):
    • Function Code: 03
    • Starting Address: 00 00 (читаем с логического адреса 0, что соответствует регистру 40001)
    • Quantity: 00 0A (10 в hex)
      Итого PDU: 03 00 00 00 0A
  3. Склеиваем: 00 00 00 00 00 06 FF 03 00 00 00 0A
Отправляем через netcat: echo -ne "\x00\x00\x00\x00\x00\x06\xFF\x03\x00\x00\x00\x0A" | nc -q 1 target_ip 502

В ответ получим что-то вроде: 00 00 00 00 00 17 FF 03 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Разбираем: MBAP заголовок ответа, затем 03 (функция), затем 14 (20 байт данных, т.е. 10 регистров по 2 байта), и потом сами данные - в данном примере сплошные нули.

Практические инструменты (наш арсенал):
  1. Nmap: Старый добрый разведчик. Имеет скрипты для Modbus.


    Bash:
    nmap -p 502 --script modbus-discover target_ip

    Скрипт modbus-discover попробует определить Unit ID, перебрать функции, получить идентификатор устройства. Более агрессивный вариант:
    Bash:
    nmap -p 502 --script modbus-discover,modbus-enum --script-args='modbus-enum.rootfolder=/usr/share/nmap/nselib/data/modbus/' target_ip
  2. mbcheck (из набора mbtools): Утилита для разведки и базового тестирования.

    Bash:
    mbcheck -t target_ip -p 502
    Покажет поддерживаемые функции, может попробовать читать регистры.

  3. Plcscan: Мощный инструмент для сканирования и фингерпринтинга ПЛК не только по Modbus.

    Bash:
    python plcscan.py -t target_ip
  4. modbus-cli: Швейцарский нож для работы с протоколом из командной строки. Идеально для автоматизации.

    Bash:
    # Чтение 10 регистров с адреса 0
    modbus read --unit=1 target_ip holding-registers 0 10
    # Запись значения 1000 в регистр 0
    modbus write --unit=1 target_ip holding-register 0 1000

  5. Python + библиотека pymodbus: Для кастомных скриптов. Вот пример простого сканера регистров:

    Python:
    from pymodbus.client import ModbusTcpClient
    import struct
    
    client = ModbusTcpClient('target_ip', port=502)
    client.connect()
    
    # Пытаемся прочитать блок регистров
    for start_addr in range(0, 100, 10): # Сканируем с 0 до 100 с шагом 10
        try:
            rr = client.read_holding_registers(start_addr, 10, unit=1)
            if not rr.isError():
                print(f"Registers {start_addr}-{start_addr+9}: {rr.registers}")
                # Попробуем интерпретировать как float (часто используется для показаний)
                if len(rr.registers) >= 2:
                    # Предполагаем, что два соседних регистра (4 байта) - это float IEEE 754
                    hex_val = struct.pack('>HH', rr.registers[0], rr.registers[1]) # Big-endian порядок байт
                    float_val = struct.unpack('>f', hex_val)[0]
                    print(f"  As float (regs {start_addr},{start_addr+1}): {float_val}")
        except Exception as e:
            print(f"Error at {start_addr}: {e}")
    client.close()

  6. Wireshark: Незаменим для анализа трафика. В нём есть диссектор Modbus/TCP. Можно фильтровать по modbus. Видно все запросы, ответы, коды функций. Если есть легитимный трафик с HMI-станции - это золотая жила для понимания логики: какие регистры читаются/пишутся, с какой периодичностью.
Сценарии эксплуатации (теоретические, исключительно в образовательных целях):
  1. Разведка и картографирование: Первым делом - чтение регистров (функции 03, 04) и кайлов (01, 02). Цель - построить карту памяти ПЛК. Где лежат уставки? Где текущие технологические параметры? Где команды управления? Часто помогает документация к ПЛК конкретной модели (легко гуглится), ибо адресация типовых функций (пуск/стоп двигателя) часто стандартна.
  2. Манипуляция процессами:
    • Принудительная остановка: Запись 0 в регистр, отвечающий за команду «Пуск» двигателя, или запись 1 в регистр «Аварийный останов».
    • Изменение уставок: Запись в регистры уставок температуры, давления, уровня. Например, поднять уставку максимального давления в ёмкости, отключив при этом аварийную защиту (записав 0 в соответствующий бит дискретного выхода). Это классический путь к физическому разрушению.
    • Подмена показаний: Теоретически, Modbus не поддерживает «запись» в регистры входов (только чтение). Но! Если атакующий находится на пути трафика (MitM), он может подменять ответы от ПЛК на запросы от HMI. Показать оператору, что температура в норме, хотя на самом деле она зашкаливает.
  3. DoS (Отказ в обслуживании): Примитивно, но эффективно. Лавина запросов на чтение/запись может перегрузить ресурсы ПЛК (многие старые модели имеют ограниченную вычислительную мощность и сетевой стек), что приведёт к остановке цикла опроса SCADA и потери управления. Или отправка некорректного PDU, приводящего к падению сервиса Modbus на устройстве (требуется перезагрузка).
Главная уязвимость Modbus - доверие. Никто не проверяет, от кого пришёл пакет. Если ты в сегменте сети - ты хозяин всех ПЛК. Никаких паролей, никаких ключей.

1769977815636.webp


Часть 3: BACnet. Язык умных зданий, или как поговорить с кондиционером на его диалекте.

Если Modbus - это цеха и насосные, то BACnet (Building Automation and Control Networks) - это царство HVAC (Отопление, Вентиляция, Кондиционирование), освещения, контроля доступа и пожарной сигнализации в умных зданиях. Офисы, аэропорты, гостиницы, больницы. Протокол более высокоуровневый, сложный и... интересный.

Философия и архитектура:
BACnet изначально задумывался как стандарт (ANSI/ASHRAE 135, ISO 16484-5) для интеграции устройств разных вендоров. В его основе лежит объектная модель. Каждое устройство (устройство BACnet) содержит в себе объекты. Типы объектов стандартизированы: Аналоговый Вход (AI), Аналоговый Выход (AO), Двоичный Вход (BI), Двойный Выход (BO), Устройство (Device) и т.д. У каждого объекта есть свойства (Properties): Present_Value (текущее значение), Description, Units, Priority_Array (ключевая вещь для управления!) и другие.

Для транспорта используется целый букет: BACnet/IP (порт UDP 47808 - запомни это число!), BACnet Ethernet (MS/TP - мастер-ведомый/терминальный проходной, по последовательной линии). BACnet/IP - это наш главный интерес.

Ключевые концепции, которые нужно понять:
  1. Device ID: Уникальный в сети BACnet идентификатор устройства (от 0 до 4194303). Аналог Unit ID в Modbus, но более глобальный.
  2. Сервисы (Services): BACnet - это протокол типа «клиент-сервер» с богатым набором сервисов. Наиболее важные для нас:
    • Who-Is / I-Am: Механизм обнаружения устройств. Рассылается широковещательный запрос Who-Is («Кто тут?»). Устройства, чей Device ID попадает в указанный диапазон, отвечают пакетом I-Am, содержащим их ID, IP-адрес, и прочую информацию. Это дверь для разведки.
    • Read-Property / Write-Property: Чтение и запись свойств объектов. Основа управления. Например, прочитать Present_Value аналогового входа (температуру) или записать Present_Value двоичного выхода (включить реле).
    • Subscribe-COV (Change of Value): «Подписка» на изменение свойства. Устройство будет само присылать обновления при изменении значения. Используется для эффективного мониторинга.
  3. Приоритеты записи (Priority_Array): Гениальная и опасная фича. У каждого объекта с возможностью записи (например, Analog Output, отвечающий за положение клапана) есть массив приоритетов из 16 слотов (приоритеты 1-16, где 1 - наивысший). Запись в свойство содержит не только значение, но и приоритет. Устройство всегда исполняет команду с наивысшим приоритетом. Приоритет 16 (самый низкий) обычно зарезервирован за «ручным» управлением с панели оператора. Более высокие приоритеты могут быть у автоматики, графиков, систем пожарной сигнализации (у которой часто приоритет 3 или даже 1 - приказной!). Атакующий, зная эту систему, может записать команду с приоритетом, например, 5, перебив ручное управление, но ещё не трогая пожарную систему.
Практические инструменты для BACnet:
  1. Nmap: Опять наш друг.

    Bash:
    nmap -sU -p 47808 --script bacnet-info target_ip
    Скрипт bacnet-info отправляет Who-Is и разбирает ответы I-Am, показывая Device ID, имя модели, вендора и т.д.
  2. YABE (Yet Another BACnet Explorer): Это Must Have. Кроссплатформенный (Java) графический explorer. Позволяет в визуальном режиме:
    • Сканировать сеть на устройства BACnet.
    • Просматривать иерархию устройств, их объектов и свойств.
    • Читать и записывать свойства (в том числе с указанием приоритета!).
    • Создавать тренды, графики.
      Это «хаб» для исследования сети BACnet. Интерфейс староват, но функционал мощнейший.
  3. BACnet Stack (например, BACnet/IP Stack from Steve Karg): Набор утилит командной строки. Полезно для автоматизации.
    • bacwi (BACnet Who-Is): для сканирования.
    • bacrp (BACnet Read Property): чтение свойства.
    • bacwp (BACnet Write Property): запись свойства.
    • Bash:
      # Отправить Who-Is широковещательно
      bacwi
      # Прочитать Present_Value (свойство 85) аналогового входа (объект AI) с instance 1 устройства с ID 123456
      bacrp 123456 analog-input 1 85
      # Записать Present_Value в аналоговый выход (AO) instance 2 на значение 100.0 с приоритетом 8
      bacwp 123456 analog-output 2 85 16 100.0 -p 8
    (Примечание: свойства часто обозначаются кодами, 85 = Present_Value, 1 = Object_Identifier и т.д.)

  4. Wireshark: Имеет отличный диссектор BACnet. Можно детально разбирать любые сервисы, смотреть приоритеты, значения.
Сценарии эксплуатации BACnet (опять же, чистая теория для понимания векторов):
  1. Пассивная разведка: Прослушивание UDP 47808. В активной сети BACnet постоянно идут Who-Is/I-Am, Read/Write-Property, COV-уведомления. Можно составить полную карту системы: какие устройства есть, какие объекты они содержат, какие значения в них сейчас.
  2. Активное сканирование: Рассылка Who-Is запросов. В ответ получаем россыпь I-Am. Часто в них есть Model Name, Vendor Name, Firmware Revision. По этим данным легко искать известные уязвимости (CVE) для конкретных контроллеров, термостатов, шлюзов.
  3. Чтение конфиденциальных данных: BACnet может хранить не только температуру. В свойствах объектов Description, Object_Name могут быть текстовые описания вроде «Серверная №3, верхний кондиционер». В устройствах контроля доступа могут быть списки карт (как свойства объектов). Всё это читается через Read-Property.
  4. Манипуляция системами здания:
    • Терроризировать офис: Найти объекты Binary Output, отвечающие за реле освещения в open-space, и начать хаотично их включать/выключать с записью Write-Property. Или выставить температуру на всех кондиционерах на +35°C летом или -10°C зимой.
    • Отключить вентиляцию в критическом помещении: Найти Analog Output, управляющий клапаном приточной вентиляции, и записать ему 0 (закрыть).
    • Вмешаться в пожарную сигнализацию: Это самая опасная часть. Объекты типа Binary Input могут быть датчиками дыма. Можно попробовать подписаться на них (Subscribe-COV) для мониторинга. Запись в выходы, управляющие оповещением или подрывом клапанов дымоудаления, требует очень высокого приоритета (чтобы перебить логику пожарной панели), но теоретически возможно, если система сконфигурирована с ошибками. ВАЖНО: Это уже не шалости, это угроза жизни людей.
    • Приоритетные атаки: Запись команд с приоритетом, например, 6, которая перебьёт штатные графики работы (приоритет ~10) и ручное управление (16), но будет проигнорирована более важными системами. Это может создать долгосрочную, трудно диагностируемую проблему («почему у нас в会议室 всегда холодно, хотя мы выставляем 23°C?»).
  5. DoS через «призрачные» устройства: Отправка множества I-Am ответов с несуществующими Device ID может замусорить память штатных BACnet-клиентов (workstations, шлюзов), которые пытаются построить карту сети. Или отправка запросов Subscribe-COV на все объекты, создавая лавину трафика.
Проблемы безопасности BACnet:
  1. Слабые или стандартные пароли: В BACnet есть концепция «парольной аутентификации» (Authenticated сервисы), но она редко используется. А если используется, то пароль часто стандартный (например, пустой) или простой.
  2. Широковещательная природа: Кто-Is рассылается на broadcast-адрес. Ответы I-Am тоже могут быть широковещательными. Это значит, что, находясь в одном VLAN/Broadcast домене, ты видишь всё.
  3. Избыточная информативность: Протокол слишком откровенен. Он сам расскажет о своей структуре любому, кто спросит.

Часть 4: Практикум - от разведки до POC. Лабораторная среда.

ВНИМАНИЕ: ВСЁ ДАЛЬНЕЙШЕЕ - ИСКЛЮЧИТЕЛЬНО ДЛЯ ТЕСТИРОВАНИЯ В ИЗОЛИРОВАННЫХ ЛАБОРАТОРНЫХ УСЛОВИЯХ НА СОБСТВЕННОМ ОБОРУДОВАНИИ.

Нет ничего лучше практики. Но покупать промышленный ПЛК за тысячи долларов - не вариант. К счастью, есть эмуляторы и софт, который позволяет поднять свою мини-OT-сеть на виртуалке.

Создание тестовой среды:
  1. Modbus:
    • pymodbus (simulator): Библиотека pymodbus содержит сервер. Можно быстро поднять эмулятор ПЛК.

      Python:
      # server_simulator.py
      from pymodbus.server import StartTcpServer
      from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext
      
      # Инициализация хранилища данных: coils, discrete inputs, holding registers, input registers
      store = ModbusSlaveContext(
          di=ModbusSequentialDataBlock(0, [0]*100),     # Discrete Inputs
          co=ModbusSequentialDataBlock(0, [0]*100),     # Coils
          hr=ModbusSequentialDataBlock(0, [0]*100),     # Holding Registers
          ir=ModbusSequentialDataBlock(0, [0]*100))     # Input Registers
      context = ModbusServerContext(slaves=store, single=True)
      
      # Запуск сервера на порту 5020 (порт 502 требует прав root)
      StartTcpServer(context=context, address=("0.0.0.0", 5020))
      Запустил, и у тебя есть ПЛК, отвечающий на любые запросы.

    • Модели вроде «Modbus PLC Simulator»: Есть различные бесплатные и платные симуляторы с GUI, где можно настраивать отклики регистров, связывать их с виртуальными датчиками.
  2. BACnet:
    • YABE (в режиме симулятора): YABE может работать как BACnet Device Simulator. Можно создать виртуальные устройства с объектами и играться с ними.
    • BACnet Stack (Steve Karg): В комплекте есть демоны bacserv и bip (BACnet/IP демон), которые могут эмулировать устройство.

      Bash:
      # Запуск простого BACnet устройства с Device ID 123456
      bacserv 123456

    • Более продвинутые симуляторы: VTS (Visual Test Shell), Building Simulator от некоторых вендоров.
Пошаговый сценарий исследования Modbus (в лаборатории):
  1. Обнаружение: nmap -p 5020 -sV lab-host (увидим открытый порт и, возможно, сервис).
  2. Идентификация: mbcheck -t lab-host -p 5020. Узнаём поддерживаемые функции.
  3. Сканирование памяти: Пишем простой скрипт на Python с pymodbus, который перебирает адреса holding registers (0x03) и input registers (0x04) блоками. Цель - найти не-нулевые значения или закономерности.
  4. Поиск логики: Если мы знаем, что эмулируем, скажем, насосную станцию, мы можем искать:
    • Регистры с плавающими значениями (давление, расход) - это, скорее всего, input registers.
    • Регистры с фиксированными круглыми числами (уставки) - holding registers.
    • Coils с состояниями 0/1 (пуск/стоп, авария).
  5. Маппинг: Составляем таблицу: Адрес | Тип | Возможное назначение | Текущее значение.
  6. Тест записи: Пытаемся записать в найденный holding register заведомо безопасное значение (в пределах нормы), наблюдаем, изменилось ли что-то в эмуляторе или в показаниях input registers.
Пошаговый сценарий исследования BACnet (в лаборатории):
  1. Обнаружение: nmap -sU -p 47808 --script bacnet-info lab-host. Получаем Device ID и детали.
  2. Исследование в YABE: Добавляем устройство по найденному IP и Device ID. Разворачиваем дерево объектов. Смотрим свойства каждого интересного объекта (AI, AO, BI, BO).
  3. Чтение критических свойств: Для аналоговых входов читаем Present_Value, Units, Description. Для выходов - ещё и Priority_Array.
  4. Анализ приоритетов: Смотрим, какие приоритеты уже заняты (не равны NULL). Определяем «окно» для атаки - приоритет, который перебьёт ручное управление, но не тронет аварийные системы.
  5. POC-воздействие: Выбираем безопасный объект (например, AO, который в симуляторе меняет цвет лампочки). Пытаемся записать ему новое Present_Value с приоритетом 8 через YABE или bacwp. Наблюдаем изменение.

Часть 5: Защита (или Как не стать героем следующей новости).

Понимание атаки - это 90% защиты. Здесь нет серебряной пули, только комплекс мер, который начинается с отказа от самообмана.
  1. Сетевая сегментация - священный грааль. OT-сеть должна быть физически или логически (VLAN) отделена от IT-сети. Связь только через строго контролируемый демилитаризованный периметр (DMZ). Не напрямую, а через серверы-посредники (Data Diode, OPC-сервер с односторонней связью).
  2. Firewall с глубоким анализом протоколов (DPI): Не просто блокировать порты, а анализировать содержимое Modbus/BACnet пакетов. Правила должны быть белыми списками:
    • Разрешать Modbus TCP только с определённых IP-адресов (HMI, инженерных станций) на определённые IP-адреса ПЛК.
    • Разрешать только определённые коды функций (например, запретить Write функции с внешних сетей).
    • Для Modbus: фильтровать по диапазонам адресов. Запрещать запись в регистры, отвечающие за критичные команды, с любых адресов, кроме доверенных.
    • Для BACnet: Фильтровать Who-Is/I-Am широковещательные пакеты, не пуская их за пределы сегмента. Ограничивать выполнение сервисов Write-Property с определённых источников и на определённые объекты/приоритеты.
  3. Отказ от дефолтных конфигураций: Изменить дефолтные порты (хотя это security through obscurity, но это дополнительный барьер), изменить дефолтные Unit ID в Modbus и Device ID в BACnet. Отключить неиспользуемые сервисы.
  4. Внедрение контроля целостности и мониторинга аномалий: Системы вроде Industrial IDS (например, Nozomi Networks, Claroty, Dragos). Они умеют строить базовую линию нормального поведения протоколов: какие устройства с кем общаются, какие функции используют, какие диапазоны адресов читают. Любое отклонение (например, запись в регистр с адреса, с которого обычно только читают) - тревога.
  5. Аутентификация и шифрование (где возможно):
    • Для Modbus: Существуют расширения Modbus Secure (с использованием TLS), но поддержка крайне мала. Основная надежда - на VPN туннели между узлами или защита на сетевом уровне.
    • Для BACnet: Есть BACnet/SC (Secure Connect), использующий TLS 1.3 и современную аутентификацию. Это будущее, но миграция на него медленная. До его внедрения - изоляция, изоляция и ещё раз изоляция.
  6. Физическая безопасность и процедуры: USB-порты на ПЛК и HMI должны быть закрыты заглушками или отключены в BIOS. Жёсткий контроль съёмных носителей. Разделение обязанностей. Регулярный аудит конфигураций.
Не вини инженеров. Вместо этого, обучи их. Покажи им, как с помощью YABE или простого скрипта можно за 5 минут «выключить свет» в их же виртуальной модели. Когда человек видит угрозу своими глазами, он становится самым ярым её противником. Создавай совместные команды из IT-безопасников и OT-инженеров. Без знания технологических процессов первым нечего ловить в этой сети.

1769977833472.webp


Эпилог

От первоначального, почти наивного удивления перед фактом существования этих «динозавров» в сердце современной инфраструктуры, через технические дебри структур пакетов, кодов функций и приоритетных массивов, к практическим скриптам и методам защиты. Если ты дошёл до этого места, прочитав (или хотя бы пробежав глазами) эти десятки тысяч слов, то твоя картина мира уже не может быть прежней. Ты больше не увидишь безликий «завод» или «умное здание» - ты увидишь слоистую архитектуру, в основании которой лежит хрупкий, прозрачный и невероятно ответственный цифровой фундамент.

Это знание - мощный инструмент. И, как любой инструмент подобной силы, оно обременяет грузом ответственности. Давай начистоту, без пафоса, но и без иллюзий, обсудим, что с этим грузом делать.

Ответственность: между исследователем и вандалом

Эксплуатация уязвимостей в промышленных системах - это не «пентест в отместку корпорациям» и не безобидное хулиганство. Это потенциально:
  • Экологическая катастрофа: Сброс неочищенных стоков в реку из-за манипуляций с контроллерами очистных сооружений. Выброс химикатов в атмосферу из-за нарушения режима работы скрубберов.
  • Техногенная авария: Разрыв трубопровода из-за сброса давления или, наоборот, превышения допустимого. Взрыв или пожар на технологической установке из-за нарушения температурного режима.
  • Угроза жизни и здоровью: Отключение вентиляции в тоннеле метро или на подземной парковке. Нарушение работы медицинских газовых систем в больнице. Блокировка систем пожарного оповещения и дымоудаления.
  • Социально-экономический хаос: Длительное отключение электроснабжения района или города. Сбой в логистике топлива. Остановка производства лекарств или продуктов питания.
Когда ты в лаборатории эмулируешь запись в регистр 40001, ты играеь с абстракцией. В реальном мире по адресу 40001 может висеть бит «Пуск главного циркуляционного насоса реакторного контура». Разница - не в технике, а в последствиях. Настоящий хакерский дух - это не только понимание системы, но и понимание контекста, в котором она работает, и веса каждого байта, который ты отправляешь.

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

Граница проходит не по технической сложности действия (прочитать Modbus-регистр технически тривиально), а по праву и последствиям.

Роль исследователя: не найти дыру, а зашить весь свитер

Если ты принимаешь эту ответственность, то твоя роль меняется с потенциального агрессора на критически важного защитника. Но защитника особого рода - не того, кто ставит «галочки» в соответствии с регламентом, а того, кто мыслит как атакующий, чтобы опередить его.
  1. Ты - переводчик между мирами. Ты теперь можешь объяснить инженеру OT на его языке (процессы, уставки, надёжность), почему его сеть - это Swiss cheese для любого, кто к ней подключится. И наоборот, ты можешь объяснить CISO (главному по инфобезопасности) на языке рисков и векторов атак, почему он не может просто заблокировать порт 502 на фаерволе и считать дело сделанным. Ты становишься мостом, без которого никакая реальная безопасность невозможна.
  2. Ты - археолог и картограф. Задача - не взломать, а каталогизировать. Составить точную, детализированную карту всех промышленных активов: какие ПЛК, с какими версиями прошивок, какие протоколы, какие точки ввода-вывода, какая логика управления. Эта карта - основа для любого осмысленного мониторинга и защиты. Без неё ты слеп.
  3. Ты - разработчик контрмер, а не эксплойтов. Вместо скрипта для записи во все регистры подряд, твой выход - это скрипт для валидации трафика. Скрипт, который, слушая порт 47808, кричит тревогу, если видит Write-Property с высоким приоритетом с IP-адреса, не входящего в белый список. Вместо поиска дефолтных паролей в BACnet - это разработка процедур безопасного ввода в эксплуатацию новых устройств с обязательной сменой всех дефолтных конфигураций.
Будущее: между наследием и революцией

Куда всё движется? Есть два пути.

Путь первый (печальный, но вероятный): Инкрементальные улучшения. Фаерволы с глубоким анализом протоколов (DPI) станут чуть более распространёнными. Появится больше систем мониторинга аномалий в OT-трафике. BACnet Secure Connect и Modbus over TLS будут медленно, с скрипом, внедряться в новых проектах. Но гигантская инерция установленной базы (legacy systems) останется с нами ещё на 30-40 лет. Задача защитника - выстроить вокруг этого наследия такие оборонительные периметры и такие практики мониторинга, чтобы сделать атаку на него максимально дорогой, шумной и обнаруживаемой. Это путь «управляемого риска».

Путь второй (сложный, но необходимый): Смена парадигмы. Признание того, что принципы, заложенные в Modbus и BACnet, несовместимы с современной угрозой. Это путь к разработке и внедрению промышленных протоколов изначально спроектированных с безопасностью в ядре. Где шифрование, аутентификация и контроль целостности - не опции, а обязательные базовые функции. Где устройства имеют аппаратные модули доверия (HSM). Где сетевая архитектура строится на принципах zero-trust («никому не верь») даже внутри OT-сегмента. Это потребует колоссальных инвестиций, пересмотра образовательных программ для инженеров и, возможно, жёсткого регулирования.

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

Напутствие

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

Поэтому финальный посыл таков:
  • Если ты исследователь - исследуй ответственно. Публикуй свои находки, делая акцент на методах обнаружения и защиты, а не на готовых эксплойтах. Работай с вендорами через ответственное разглашение уязвимостей.
  • Если ты инженер OT/АСУ ТП - перестань считать кибербезопасность «головной болью этих IT-шников». Это твоё оборудование, твой процесс, твоя ответственность. Начни с малого: потребуй сетевую схему, начни вести реестр устройств, заблокируй неиспользуемые порты, отключи ненужные сервисы.
  • Если ты специалист по IT-безопасности - прояви понимание. Не приходи в цех с лекцией о продвинутых Persistent Threats. Приди и спроси: «Как это работает? Что самое важное? Что нельзя останавливать ни при каких обстоятельствах?». Учи их язык.
Мы стоим на пороге эры, где цифровое и физическое окончательно переплелись. Старые, доверчивые протоколы - это ахиллесова пята этой новой реальности. Мы не можем вырвать их - слишком многое на них держится. Но мы можем, вооружившись знанием, прямотой и солидарностью, начать бережно укреплять это слабое место. Не для того, чтобы играть в войнушку, а для того, чтобы свет в розетке был всегда, вода - чистой, а воздух в больничной палате - свежим.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab