Язык программирования Lua в системе SIEM

«Большинство считает, что Lua — язык для игр или скриптов в Nginx. Но его настоящая сверхспособность — превращать монолитные системы мониторинга безопасности в живые, программируемые среды. За счёт минимализма он становится универсальным адаптером между несвязанными системами, позволяя писать логику безопасности, которая учитывает контекст, а не просто следует правилам.»

Архитектура Lua: малое ядро в ядре SIEM

Lua не пытается быть языком для всего. Его цель — быть идеальным компонентом. В основе лежит минимальное ядро, реализующее базовый синтаксис, управление памятью и метамеханизмы. Вся стандартная библиотека — подключаемые модули. Эта модульность зеркально отражается в его роли внутри SIEM: Lua-движок внедряется в платформу как компактная виртуальная машина, получая доступ только к тем API и данным, которые разрешены. Это архитектурное решение делает его безопасным (скрипт не может «сломать» ядро SIEM) и быстрым, так как накладные расходы на вызовы C-функций минимальны.

Ключевые особенности для безопасности

Для инженера, работающего с системами мониторинга и реагирования, ключевыми становятся не академические парадигмы, а конкретные свойства языка, решающие оперативные задачи.

Особенность Практический смысл для SIEM
Встраиваемость (C API) Позволяет разработчикам SIEM «научить» язык работать напрямую с внутренними структурами данных событий, без дорогостоящего парсинга JSON. Lua-скрипт получает событие как нативную Lua-таблицу за микросекунды.
Динамическая типизация и таблицы Основная структура данных — таблица — идеально ложится на иерархические события (source.ip, user.name). Нет необходимости заранее описывать схемы, что критично при обработке логов от новых источников.
Автоматическое управление памятью Исключает утечки памяти в долгоживущих правилах корреляции, которые обрабатывают миллионы событий. Сборщик мусора работает инкрементально, не вызывая заметных пауз в реальном времени.
Корутины Менее очевидная, но мощная фича. Позволяет писать асинхронные сценарии, которые «ставят на паузу» ожидание ответа от внешней системы (например, API базы уязвимостей), не блокируя обработку других событий.

Практическое применение: от парсера до SOAR

В контуре безопасности Lua эволюционирует от простого скриптового инструмента до стержня программируемой логики реагирования.

Нормализация и обогащение событий

До корреляции событие нужно понять. На Lua пишутся парсеры для специфичных, плохо документированных логов, которые стандартные коннекторы не берут. Следующий шаг — обогащение: скрипт по IP-адресу из события запрашивает из CMDB отдел владельца, добавляя в событие поле `asset.owner`. Эта дополнительная размерность — ключ к точным правилам, например, «множественные сбои входа для учётной записи из отдела финансов».

Корреляция с контекстом и состоянием

Статические правила типа «5 неудачных входов за 5 минут» легко обойти. На Lua можно реализовать машину состояний. Например, правило отслеживает цепочку: 1) неудачный вход с неизвестного IP, 2) успешный вход с того же IP через 2 минуты, 3) попытка доступа к сетевому ресурсу, к которому у пользователя обычно нет прав. Каждое событие переводит внутренний счётчик (таблицу Lua) в новое состояние. Это уже не подсчёт, а выявление тактики злоумышленника.

Автоматизированное реагирование (SOAR)

Здесь Lua выступает как язык оркестрации. По триггеру правила скрипт может выполнять не одно, а целое расследование: запросить у EDR детальную информацию о процессе, проверить IP в Threat Intelligence-фиде, создать инцидент в тикет-системе и, если уверенность высока, отправить в сетевой экран команду на временную блокировку. Всё это — в рамках одной транзакции выполнения, с обработкой ошибок на каждом шаге.

Синтаксис для инженера ИБ

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

Конструкция Пример Применение в контексте
Условие и логические операторы
if event.severity > 7 and event.source.ip ~= internal_net then
  raise_alert(event)
end
Базовое правило фильтрации, комбинирующее атрибуты события.
Итерация по массиву событий
for _, evt in ipairs(event_batch) do
  enrich_with_dns(evt)
end
Пакетная обработка, часто используется в правилах агрегации за временное окно.
Функции и модульность
local ti = require('threat_intel')
function check_malicious_ip(ip)
  return ti.lookup(ip) ~= nil
end
Вынос повторяющейся логики (проверка IP, парсинг) в отдельные модули для повторного использования.
Таблицы (хэш-карты)
suspicious_users = {
  ["svc_admin"] = { first_seen = os.time(), attempt_count = 0 }
}
suspicious_users["svc_admin"].attempt_count = 1
Сохранение состояния между разными событиями — основа для сложной корреляции.

Пример сценария: обнаружение латерального перемещения

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

-- Кэш для отслеживания успешных входов и последующих команд
local host_activity_cache = {}

-- Функция обработки нового события
function process_auth_event(event)
  if event.action == "LOGIN_SUCCESS" then
    -- Ключ: пользователь + целевой хост
    local key = event.user .. "@" .. event.dst_host
    host_activity_cache[key] = {
      timestamp = event.time,
      source_ip = event.src_ip,
      -- Инициализируем счётчик подозрительных команд
      suspicious_cmd_count = 0
    }

  elseif event.action == "REMOTE_COMMAND" then
    -- Ищем предыдущий успешный вход для этого пользователя на этот хост
    local key = event.user .. "@" .. event.dst_host
    local session = host_activity_cache[key]

    -- Если сессия найдена и команда выполняется с другого хоста в короткое время
    if session and
       session.source_ip ~= event.src_ip and
       (event.time - session.timestamp) = 2 then
        create_alert({
          title = "Подозрение на латеральное перемещение",
          description = string.format(
            "Пользователь %s после входа с %s выполняет команды с %s",
            event.user, session.source_ip, event.src_ip
          ),
          severity = 9,
          evidence = {session, event}
        })
        -- Очистка кэша для этой сессии после алерта
        host_activity_cache[key] = nil
      end
    end
  end
end

Этот скрипт демонстрирует, как Lua позволяет хранить сложное состояние между событиями, реализуя логику, недоступную для простых правил на SQL или декларативных языках.

Итог: программируемая граница обороны

Использование Lua в SIEM — это сдвиг парадигмы. Система перестаёт быть «чёрным ящиком» с предустановленными правилами. Она становится программируемой средой, где инженер службы безопасности может на лету адаптировать логику анализа под специфику своей инфраструктуры и тактики угроз. Минимализм языка оборачивается его главной силой: он не диктует, как решать задачу, а предоставляет примитивы для реализации собственной логики. В конечном счёте, это делает систему защиты не просто автоматизированной, а адаптивной и интеллектуальной.

Оставьте комментарий