SRI Bypass через CDN Race: как гонка загрузки ломает защиту скриптов

SRI Bypass через CDN Race: как гонка загрузки ломает защиту скриптов

Subresource Integrity (SRI) — это механизм, который разработчики используют, чтобы защититься от подмены внешних ресурсов, например JavaScript-библиотек, загружаемых с CDN. В идеале, если злоумышленник попытается изменить файл, браузер обнаружит несоответствие хэша и просто не выполнит код.

На практике же всё не так однозначно. Существует сценарий, известный как CDN race, при котором злоумышленник может обойти проверку SRI за счёт особенностей работы CDN и параллельной загрузки ресурсов браузером. Эта техника не нова, но остаётся актуальной, особенно в больших проектах с высокой нагрузкой и сложными цепочками кеширования.

Что такое SRI и зачем он нужен

SRI ( Subresource Integrity ) — это атрибут integrity, который добавляют к тегу <script> или <link>. Он хранит хэш содержимого файла (обычно SHA-256, SHA-384 или SHA-512). Когда браузер загружает ресурс, он вычисляет его хэш и сверяет с указанным в атрибуте. Если совпадения нет, файл отбрасывается.

Пример использования:

<script src="https://cdn.example.com/lib.js"
         integrity="sha384-abc123..."
         crossorigin="anonymous"></script>
 

Это полезно, если вы не полностью доверяете стороннему хостингу. Даже если CDN будет скомпрометирован, браузер защитит пользователя, отказавшись исполнять модифицированный код.

Как работает CDN race

CDN race — это ситуация, при которой разные серверы CDN могут одновременно отдавать разные версии одного и того же файла в зависимости от точки присутствия (PoP) и состояния кеша. Из-за распределённой природы CDN и особенностей обновления контента могут возникнуть "окна" времени, когда часть узлов уже содержит обновлённый (или вредоносный) файл, а другая часть — нет.

Ключевой момент — браузер может параллельно загружать один и тот же ресурс в разных контекстах, например:

  • Один и тот же скрипт подключён несколько раз с разными параметрами.
  • Скрипт загружается как модуль (type="module") и как обычный скрипт.
  • Есть прелоад (<link rel="preload">) и фактическая загрузка.

Если один из запросов получит "чистую" версию и пройдет SRI-проверку, а другой — вредоносную, может возникнуть гонка за использование кеша и исполнение кода до срабатывания проверки.

Почему это вообще возможно

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

Это открывает пространство для атак:

  1. Злоумышленник модифицирует файл на части PoP CDN, но не везде.
  2. Жертва отправляет параллельные запросы к ресурсу.
  3. Браузер кеширует "чистую" версию после одной проверки.
  4. Другой контекст или механизм загрузки выполняет подменённый код, минуя повторную проверку.

Пример сценария атаки

Рассмотрим упрощённую модель:

  1. На сайте подключен main.js с SRI и crossorigin.
  2. CDN имеет PoP в Лондоне и Нью-Йорке.
  3. Атакующий получает доступ к CDN в Нью-Йорке и загружает вредоносную версию.
  4. Пользователь в Европе загружает страницу, браузер через DNS балансировку отправляет один запрос в Лондон, другой — в Нью-Йорк.
  5. Лондонский PoP отдаёт легитимную версию, которая проходит SRI-проверку и кешируется.
  6. Нью-Йоркский PoP отдаёт вредоносный файл, но браузер использует уже кешированную версию или выполняет код до проверки.

В результате защита, казалось бы, есть, но она не спасает от реальной угрозы.

Почему это опасно для больших проектов

Эта техника особенно актуальна для проектов, которые:

  • Используют CDN без строгого контроля кеша.
  • Загружают один и тот же ресурс из нескольких мест (например, с параметрами ?v=).
  • Активно используют прелоад или prefetch.
  • Имеют сложные цепочки редиректов и балансировщиков.

Чем сложнее инфраструктура, тем больше вероятность, что где-то можно создать условия для гонки загрузки.

Как защититься от CDN race

Полностью исключить этот риск сложно, но можно минимизировать:

  • Использовать fetch API или загрузку ресурсов с ручной валидацией.
  • Отключить или минимизировать параллельные загрузки одного ресурса в разных контекстах.
  • Жёстко контролировать кеш CDN, включая принудительную синхронизацию PoP перед деплоем.
  • Использовать версионирование файлов и загружать уникальные имена при каждом обновлении.
  • По возможности хранить критические скрипты на собственных серверах.

Инструменты для тестирования

Если вы хотите проверить свой проект на устойчивость к подобным атакам, можно использовать:

  • SecurityHeaders — для проверки SRI и других заголовков.
  • Собственные тестовые CDN с эмулированием задержек и разных версий файлов.
  • Инструменты вроде mitmproxy для подмены ответов на лету.

Выводы

SRI — полезный механизм, но не панацея. Он защищает от подмены содержимого в большинстве случаев, но в реальной инфраструктуре с CDN остаются уязвимости. CDN race — один из примеров того, как архитектурные особенности могут превратить мощную защиту в дырявый щит.

Если ваш проект использует внешние ресурсы, особенно через глобальные CDN, стоит учитывать такие сценарии. А лучше — проектировать систему так, чтобы критические файлы были под вашим полным контролем.

SRI bypass Subresource Integrity CDN race веб-безопасность уязвимости защита подресурсов интегритет ресурсов Content Delivery Network
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
Антивирус для мозга!

Лечим цифровую неграмотность без побочных эффектов

Активируйте защиту — подпишитесь