
Прототип C2-канала вредоносного ПО с использованием сертификатов x509 поверх mTLS
Прежде всего, зачем я публикую это в открытом доступе?
MITRE ATT&CK упоминает только украденные или самоподписанные сертификаты, а NDR-системы (насколько мне известно) уделяют очень мало внимания содержимому x509-сертификатов, кроме того, кто является выпускающим УЦ. В целом x509-сертификаты считаются доверенными и беспрепятственно проходят через наши межсетевые экраны. Но по сути это просто файлы, которые, как и любые другие, могут легко содержать вредоносные полезные нагрузки. Мы доверяем им и игнорируем их, потому что они являются ключевым компонентом процесса шифрования, который мы начали воспринимать как должное. Основная цель этого проекта — повысить осведомлённость о классе индикаторов безопасности, которым мы привыкли доверять, и осветить методы, которые можно использовать для обнаружения вредоносного использования таких сертификатов.
Мне всегда было интересно, использовали ли злоумышленники x509-сертификаты как часть своей C2-коммуникации, не для шифрования сетевого трафика, а для того, чтобы непосредственно встраивать C2-коммуникацию в x509-сертификат. После пяти лет поисков чего-то подобного в дикой природе я наконец решил просто написать это сам, чтобы проверить, возможно ли это... возможно.
Каждое зашифрованное сообщение, отправляемое через HTTPS/TLS, становится возможным благодаря передаче x509-сертификата. При установлении TLS-рукопожатия (рисунок ниже) на четвёртом шаге сервер отправляет свой x509-сертификат клиенту. Клиент проверяет сертификат, сравнивает алгоритмы шифрования, поддерживаемые сервером, и выбирает алгоритм для всего дальнейшего обмена.

Как показано на этой диаграмме, это лишь однонаправленная передача x509-сертификата от сервера клиенту. Это плохо подходит для C2-коммуникации, поскольку у клиента нет возможности ответить серверу. В лучшем случае это можно использовать только как механизм однонаправленной передачи данных (см. раздел «Предшествующие разработки» ниже).
Но существует и другой тип TLS-сессии, называемый взаимной TLS-аутентификацией (mTLS), при котором и клиент, и сервер обмениваются x509-сертификатами для аутентификации друг друга.

Как показано на рисунке выше, при взаимной аутентификации x509-сертификат сервера отправляется клиенту для аутентификации, а затем x509-сертификат клиента отправляется серверу для аутентификации. Этот обмен артефактами представляет собой возможность создания двустороннего канала связи для C2-серверов.
Поскольку серверный и клиентский сертификаты обмениваются базовой SSL-библиотекой, у клиента нет возможности извлечь сообщение из сертификата сервера, выполнить команду и сгенерировать ответный сертификат в рамках одного mTLS-соединения. Это означает, что C2-канал должен быть спроектирован так, чтобы обмен запросом и ответом происходил через два разных взаимных TLS-соединения, примерно как в псевдо-полудуплексном режиме передачи.

Процесс запроса/ответа состоит из следующих шагов:
После того как у меня это заработало, я был весьма горд собой за свою креативность и всё такое.
Затем я наткнулся на доклад с BSides 2018 года Джейсона Ривза, который написал дроппер вредоносного ПО с использованием x509-сертификатов через TLS. Год спустя Джейсон опубликовал эту статью, описывающую полноценный двусторонний канал связи с использованием mTLS.
Для mTLS требуется, чтобы сертификаты и клиента, и сервера были подписаны одним и тем же CA-сертификатом, поэтому первым шагом необходимо сгенерировать собственную пару из закрытого ключа и сертификата УЦ.
Создайте закрытый ключ корневого УЦ:
openssl genrsa -des3 -out hmCA.key 2048
Примечание: парольная фраза не позволит никому, кто получит ваш закрытый ключ, сгенерировать собственный корневой сертификат.
Создайте сертификат корневого УЦ:
openssl req -x509 -new -nodes -key hmCA.key -sha256 -days 1825 -out hmCA.pem
Скопируйте сгенерированные файлы ключа и сертификата в папку certs/ca_certs. В проекте есть демонстрационная пара ключ/сертификат, так что при желании этот шаг можно пропустить.
Запустите клиент:
python client.py
Запустите сервер:
python server.py
Я никогда не хочу публиковать что-то потенциально вредоносное, не описав также, как обнаружить это в ваших сетевых журналах.
Можно подумать, что обнаружить такой тип TLS-паттерна легко, но это не так просто. Один из главных признаков этого C2-канала — полудуплексный стиль связи: для завершения полного цикла запрос/ответ между сервером и клиентом требуется два потока взаимной аутентификации. Это будет повторяться многократно, поскольку сервер отправляет клиенту разные команды.
Это означает, что вам следует искать:
Это выглядит как железобетонный набор правил обнаружения, но, как я уже говорил, всё не так просто. Оказывается, существует ряд корпоративных сервисов, у которых тоже похожий паттерн mTLS-трафика, в том числе:
Некоторые из них, похоже, являются службами управления активами/устройствами, поэтому теоретически они должны отправлять один и тот же набор сертификатов при каждом проходе по всем своим устройствам. Можно проверить, существуют ли наборы из нескольких mTLS-сессий, повторяющихся каждые N часов, а затем посмотреть, совпадают ли хэши сертификатов между двумя разными наборами mTLS-сессий, или совпадают в основном. Также стоит обратить внимание на то, чтобы клиентские сертификаты различались для каждой mTLS-сессии, но серверный сертификат оставался одним и тем же во всех сессиях.
SSL-инспекция — один из способов потенциально заблокировать такой тип канала C2-связи, поскольку сервер SSL-инспекции не будет иметь вредоносный CA-сертификат, необходимый для аутентификации клиентского сертификата.