Когда я только начинал свой путь в информационную безопасность, мне нравилось тестировать веб-приложения на проникновение. В основном это были инъекционные атаки, поэтому возникла идея создать свой собственный межсетевой экран, защищающий от инъекционных атак, но с современным подходом, используя машинное обучение. Изучая вопрос о построении межсетевого экрана, я пришел к следующим выводам:
Межсетевые экраны прошлого поколения:
Подход черного списка требовал ручного составления правил, которые в итоге обходились злоумышленниками. Происходило это из-за того, что для составления правил обнаружения атак использовалась регулярная грамматика (тип 3 по иерархии грамматик Хомского) [1].
Подход белого списка не может охватывать все вариации вводимых обычными пользователями данных.
Межсетевые экраны нового поколения на основе машинного обучения:
Нет необходимости создавать правила детектирования вручную.
Сочетание белых и черных списков одновременно.
Поэтому имеет смысл использовать машинное обучение, потому как таким образом возможно совершить переход от регулярных грамматик к контекстно-зависимым (тип 1 по иерархии грамматик Хомского), при этом избегая трудоёмкого процесса составления правил детектирования вручную [1].
Я решил рассмотреть случай (кейс), где взаимодействие с компонентами микросервиса происходит без использования API-шлюза. Этот случай описывается в свободно распространяемой книге от Майкрософт “.NET Microservices Architecture for Containerized .NET Applications” [2]. Такое прямое клиент-серверное взаимодействие годится для небольшого количества компонентов микросервиса. Моя задумка предполагает RESTful взаимодействие.
Способ внедрения межсетевого экрана
Далее я задумался над способом внедрения своего межсетевого экрана. Существует несколько способов:
Облачные решения третьей стороны (Cloudflare, Imperva) могут оказаться ненадежными, так как эта третья сторона будет обладать TLS-сертификатом и секретным ключом. Таким образом, их межсетевой экран будет расшифровывать и зашифровывать трафик, что приводит к риску конфиденциальности и целостности данных, так как в компании может работать внутренний злоумышленник, сливающий данные.
Аппаратный межсетевой экран требует наличие или аренды физического оборудования.
Интеграция в ПО микросервисов.
Я остановился на последнем варианте. Для того чтобы внедрить межсетевой экран, я воспользовался декоратором, шаблоном проектирования, который добавляет дополнительную функциональность (в моем случае это проверка трафика), которая будет выполняться до оконечной функции микросервиса (рисунок 1).
![Рисунок 1 - Отношение агрегации между шаблоном проектирования и оконечной функцией микросервиса. Рисунок 1 - Отношение агрегации между шаблоном проектирования и оконечной функцией микросервиса.](https://habrastorage.org/getpro/habr/upload_files/60b/3f0/29d/60b3f029dc874747b6499f525a7be9a2.png)
На рисунке 2 представлена схема, где создаваемый межсетевой экран работает как частичный прокси (half-proxy). Такой способ взаимодействия позволяет провести оптимизацию DSR (Direct Server Return). Это полезно, в случае если с сервера возвращается большой ответ. Таким образом, создаваемый межсетевой экран работает на прикладном уровне модели OSI (L7) для проверки параметров методов HTTP(S). При этом, если от клиента приходит безопасный трафик, то возврат по DSR, иначе пакеты отбрасываются.
![Рисунок 2 - Схема взаимодействия. Рисунок 2 - Схема взаимодействия.](https://habrastorage.org/getpro/habr/upload_files/1eb/897/833/1eb89783373a8afaa0657e2d7a43022b.png)
Формирование датасетов
Далее я сформировал датасеты, ниже представлен список всех классов, которые может предсказывать модель.
Классические SQL-инъекции (in-band): основанные на ошибке и с использованием union.
Слепые SQL-инъекции (blind): основанные на времени и на основе логического вывода.
Обфусцированные SQL-инъекции (blacklist).
Межсайтовый скриптинг (XSS).
Атака обхода каталога (directory traversal).
Инъекция шаблона на стороне сервера (SSTI).
Безопасный трафик (benign).
В таблице ниже представлено описание датасетов, при этом обучающий датасет был разделен в пропорции 80:20.
Наименование датасета | Количество элементов в датасете |
Обучение | 400 |
Валидация | 100 |
Тестирование | 500 |
Размер выборок – это 64 элемента формального языка, близкого к естественному (NL). Здесь нужно уточнить, что, по сути, из выборки создаётся формальный язык, близкий к естественному, но при этом методы NLP всё еще применимы.
Реализация модели
Последовательная (tf.keras.Sequential) модель реализована при помощи Python 3, Tensorflow 2 и Keras API. Она представлена на рисунке 3. Обучению подлежат только слои, выделенные пунктирной линией.
![Рисунок 3 - Стек слоёв модели Рисунок 3 - Стек слоёв модели](https://habrastorage.org/getpro/habr/upload_files/196/cc5/c2c/196cc5c2c46d39788e8892e808d917a2.png)
Ниже представлено краткое описание:
Слой текстовой векторизации (TextVectorization) нормализует входные данные (декодирует полезную нагрузку, добивает нулями вектора до длины 250) и создает словарь выборки.
Слой вложения слов (Embedding) создаёт плотные вектора и тензор становится трёхмерным.
Слой свёртки (Conv1D) хоть и предназначается для классификации изображений, но я использовал его немного иначе: вместо 4 каналов RGBA, я использовал каналы, полученные от вложения слов, то есть 64 канала. По ним и проходит окно свёртки.
Слой субдискретизации (GlobalMaxPooling1D) уменьшает размерность трехмерного тензора до двумерного, путем поиска максимального элемента во второй оси тензора (в Tensorflow эта ось именуется timesteps [3]).
Полносвязный слой (Dense) умножает входную матрицу на матрицу размером 64x7.
Слой активации производит окончательное предсказание одной из 7 меток класса.
Как говорилось в первом пункте, в данной реализации пришлось создать свой собственный словарь формального языка для создания контекстно-зависимой грамматики, так как готовые подходы, например, word2vec реализуют контекстно-свободную грамматику (контекстно-независимую), а BERT хоть и учитывает контекст, но тяжеловесна и нужна для обработки естественных языков. Более того, я специально вынес слой активации отдельно от полносвязного слоя (Dense). Это нужно по следующим причинам:
График сигмоиды “прижимается” к асимптотам y=1 и y=0 для значений x>2 и x<−2, что позволяет делать четкие предсказания классов. Если бы она была в Dense слое, то нейрон смещения смещал бы функцию активации, а мы этого не хотим.
Вынос функции активации решает и проблему исчезающего градиента: значения производной от сигмоиды находятся ближе к нулю. А по мере обратного распространения ошибки производные умножаются. Умножение малых чисел даёт ещё более малое значение, что останавливает обучение модели.
Оценка точности модели
Далее я оценивал точность разработанной модели. На рисунке 4 представлена матрица ошибок, полученная с помощью mlxtend:
По диагонали представлены TP значения.
В классе “Инъекция шаблона на стороне сервера” (SSTI) произошла FN ошибка, 10% элементов Инъекции на стороне сервера отнесено в Межсайтовый скриптинг.
Целочисленное значение в ячейке – это количество элементов рассматриваемого класса.
Сумма всех целочисленных значений ячеек равна 64.
![Рисунок 4 - Матрица ошибок Рисунок 4 - Матрица ошибок](https://habrastorage.org/getpro/habr/upload_files/caa/77a/f56/caa77af56219d9024c35c16660540fa6.png)
При этом я использую в качестве метрик микро-усреднение и макро-усреднение (таблица представлена ниже).
Метрика | Значение |
Micro Precision (Микро Точность) | 0,98 |
Micro Recall (Микро Полнота) | 0,98 |
Micro F1 (Микро F1-мера) | 0,98 |
Macro Precision (Макро Точность) | 0,99 |
Macro Recall (Макро Полнота) | 0,99 |
Macro F1 (Макро F1-мера) | 0,99 |
При этом микро-усреднение описывается следующим образом:
Характеристики TP, FP, FN, TN усредняются по количеству классов, а затем они подставляются в итоговую двухклассовую метрику, например полнота или F-мера.
А макро-усреднение описывается вот так:
Суммируется метрика каждого класса, например полнота, а затем результат усредняется по количеству классов.
Таким образом, разница лишь в том, что в микро-усреднении класс с маленькой мощностью почти не влияет на результат, так как его вклад в средние характеристик TP, FP, FN, TN будет незначителен, а в макро-усреднении каждый класс вносит равный вклад в итоговую метрику, так как используются величины не чувствительные к соотношению размеров классов. Помимо того, что метрика имеет высокие показатели, можно сделать вывод, что используется хорошее перемешивание, так как микро и макро метрики почти сравнялись.
Апробация модели
А после этого я провел апробацию модели на примере микросервиса, написанного на Flask:
Уязвимое к межсайтовому скриптингу приложение выложено на облачный веб-сервер Heroku.
Фаззинг параметра comment методом POST не увенчался успехом, так как с помощью декоратора подключен мой МЭ.
В итоге фаззер-грубой силы пришел к выводу, что параметр неуязвим (рисунок 5).
![Рисунок 5 - Фаззинг грубой силы не увенчался успехом Рисунок 5 - Фаззинг грубой силы не увенчался успехом](https://habrastorage.org/getpro/habr/upload_files/d06/95a/495/d0695a495f2257b6118b5d53ef8e6505.png)
При этом в логах отображается обнаружение атаки (рисунок 6).
![Рисунок 6 - Логирование предотвращения атаки Рисунок 6 - Логирование предотвращения атаки](https://habrastorage.org/getpro/habr/upload_files/154/dd6/ee6/154dd6ee63a0fdc5b229eb53f4f3003d.png)
Аналогичное произошло и с SQLmap: фаззер пришел к выводу, что параметр неуязвим, хотя на самом деле к уязвимому приложению был подключен мой межсетевой экран через декоратор.
![Рисунок 7 – SQLmap посчитал, что параметр password неуязвим из-за подключенного межсетевого экрана Рисунок 7 – SQLmap посчитал, что параметр password неуязвим из-за подключенного межсетевого экрана](https://habrastorage.org/getpro/habr/upload_files/e77/d0f/040/e77d0f0403e3fb5ea0bf8ec21022c5c8.png)
Вывод
Таким образом, мне удалось создать межсетевой экран с использованием свёрточных нейронных сетей для защиты от инъекционных атак, а также доказать применимость NLP методов для формального языка выборки. Более того, использование машинного обучения нивелирует трудоёмкий процесс составления правил детектирования инъекционных атак. В дальнейшем можно добавить защиту от L7 DDoS, добавить поддержку GraphQL и размещать модель машинного обучения в API-шлюзе.
Список использованных источников
Карпов Ю. Г. Основы построения компиляторов //Учебное пособие. Л.: Изд-во ЛПИ. – 1982. – 28 с.
de la Torre C., Wagner B., Rousos M. .NET microservices: Architecture for containerized .NET applications //Microsoft Developer Division. – 2020. – 40 c.
Введение в тензоры // [Руководство Tensorflow, 2020]. – URL: https://www.tensorflow.org/guide/tensor.
Ссылки на видео-демонстрации
Далее представлены демо-видео с обнаружением SQL-injection, directory traversal, SSTI.