Русский

Инструменты разработчика · SHA хеш-калькулятор

Целостность подресурса: как браузеры используют SHA-384 для проверки скриптов

· Фон

ша-256 base64 API-интерфейс браузера безопасность

Атрибут целостности, показывающий префикс алгоритма, дефис и дайджест base64.
Оригинальная векторная иллюстрация ToolAcre

Атрибут целостности позволяет браузеру отклонить скрипт CDN, байты которого изменились. В этом посте объясняется формат атрибута, почему SHA-384 в base64 является распространенным выбором и от чего SRI не может защитить.

CDN, который может служить чему угодно — риск цепочки поставок SRI был разработан для

Тег сценария на веб-странице может содержать атрибут целостности: `<script src="https://cdn.example.com/lib.js" integrity="sha384-..."></script>`. Значение целостности — это криптографический дайджест байтов сценария. Когда браузер загружает сценарий, он вычисляет дайджест полученных байтов и сравнивает его с атрибутом целостности. Если они совпадают, скрипт загружается. Если они не совпадают, браузер отказывается его загружать и сообщает об ошибке в консоли. Это защищает от скомпрометированного CDN, передающего измененный код, или от перехвата и изменения ответа сетевым злоумышленником.

Целостность подресурса (SRI) — это спецификация W3C, которая применяется к сценариям и таблицам стилей. Это единственная криптографическая гарантия, которую браузер может дать в отношении содержимого ресурса с перекрестным происхождением: байты должны соответствовать дайджесту, иначе ресурс будет отклонен. Это не доказывает, кто создал ресурс, а лишь то, что он не изменился с момента вычисления дайджеста. Для ресурса, обслуживаемого через HTTPS от авторитетного CDN, дайджест обеспечивает защиту от компрометации CDN или предоставления устаревшего кэшированного контента конкретно вам.

Атрибут целостности — префикс алгоритма, дефис, дайджест base64 и поддержка нескольких хэшей.

Атрибут целостности имеет определенный формат: имя алгоритма, дефис, дайджест в формате Base64. Пример: `integrity="sha384-JZDdQnrrAMe+sxxpn47in+PwhkxrCrt4SNvt+xWqV3zPJUkeFF0Qq/wNtuvNqPP5"`. Имя алгоритма может быть SHA-256, SHA-384 или SHA-512. Base64 — это кодировка, а не шестнадцатеричная; это осознанный выбор спецификации SRI. Base64 более компактен, чем шестнадцатеричный (примерно на 33% короче для того же дайджеста), что важно при встраивании в атрибуты HTML. Дефис отделяет имя алгоритма от дайджеста. Можно указать несколько значений целостности, разделенных пробелами: если хотя бы одно из них совпадает, ресурс принимается.

Почему SHA-384? Спецификация SRI допускает SHA-256, SHA-384 и SHA-512. SHA-384 стал значением сообщества по умолчанию, поскольку предлагает баланс размером /security. SHA-256 меньше (32 bytes, 44 символов в base64), но SHA-384 шире (48 bytes, 64 символов в base64) и не приводит к значительному увеличению размера атрибута по сравнению с SHA-256. SHA-512 доступен, но используется редко, поскольку его более крупный дайджест не кажется необходимым для этого варианта использования. Выбор SHA-384 является историческим и прагматичным, а не отражением превосходных свойств безопасности (все три криптографически устойчивы для этой цели).

SHA-384 предлагается и производит необходимый материал base64; предпочтения сообщества не выводятся из инструмента

Кодировка Base64 в SRI является стандартной кодировкой base64, а не base64url. Стандартный base64 использует символы + и /, которые допустимы в атрибутах HTML без процентного кодирования, хотя они имеют особое значение в URL-адресах и данных форм. Формат SRI предназначен для атрибутов HTML, а не URL-адресов, поэтому подходит стандарт base64. Если вы создаете значение целостности вручную, вы вычисляете дайджест SHA-384 (последовательность байтов), затем кодируете эти байты как стандартный base64, затем добавляете `sha384-` и вставляете в атрибут целостности.

Браузер выполняет те же действия в обратном порядке: извлекает base64 из атрибута целостности, декодирует в байты для восстановления дайджеста, вычисляет SHA-384 байтов загруженного скрипта и сравнивает два значения дайджеста. Они должны точно совпадать; однобитовая разница в дайджесте приводит к отклонению. Не существует нечеткого сопоставления или частичной достоверности: целостность является двоичной.

Для поведения SRI из разных источников требуется документация браузера помимо этого хеш-калькулятора.

SRI требует CORS для ответов из разных источников. Если вы загружаете сценарий из другого источника, сервер должен ответить `Access-Control-Allow-Origin: *` или конкретным заголовком источника, включающим ваш. Без заголовков CORS браузер не может проверить SRI, поскольку без CORS он не может подтвердить, что тело ответа соответствует тому, что сервер намеревался отправить. Заголовки CORS — это заявление сервера о том, что этот ответ можно безопасно проверить; SRI — ваша проверка правильности байтов. Вместе они образуют обязательства в цепочке поставок: сервер позволяет вам проверять контент, и вы это делаете.

Если в сценарии перекрестного происхождения отсутствуют заголовки CORS и имеется атрибут целостности, браузер загрузит его (если сценарии из этого источника разрешены CSP сайта), но не проверит целостность. Скрипт будет загружен так, как если бы атрибут целостности отсутствовал. Это не сбой SRI; это граница безопасности: вы не можете проверить ответ, который не можете прочитать.

Что происходит при несовпадении — браузер блокирует ресурс и сообщает в консоли

Когда браузер обнаруживает несоответствие целостности, он отказывается выполнять скрипт и записывает сообщение в консоль браузера. В сообщении обычно упоминаются URL, ожидаемый хэш и вычисленный хеш. Сбой является атомарным: либо ресурс загружается как есть, либо он полностью отклоняется. Частичная загрузка или откат невозможны. Если веб-сайт использовал этот сценарий и он был отклонен, сайт может сломаться. Это сделано намеренно: доставка неправильного кода хуже, чем отсутствие кода, а молчаливые сбои позволяют атакам продолжаться бесконечно.

Тестировать настройку SRI очень просто: откройте консоль браузера, загрузите страницу и найдите сообщения о несоответствии целостности. Если вы видите несоответствие, сравните вычисленный хэш, показанный в консоли, с хэшем в вашем атрибуте целостности. Если они не совпадают, пересчитайте: возможно, скрипт был обновлен и вам нужен новый дайджест.

Рабочий пример — вычисление дайджеста для скрипта и его форматирование в значение целостности, включая шаг base64.

Для вычисления дайджеста SRI вручную требуются только байты сценария и инструмент хеширования. Загрузите сценарий, вставьте его в хэш-калькулятор ToolAcre SHA, выберите SHA-384, скопируйте вывод base64 (не шестнадцатеричный), добавьте `sha384-` и вставьте в атрибут целостности. Если сценарий большой, сохраните его в файл с помощью curl или wget, а затем прочтите файл быстрее, чем вставите. Для встроенных скриптов (в теге `<script>` в HTML, а не в URL) SRI не применимо; встроенным сценариям всегда доверяют по определению. SRI предназначен для внешних ресурсов.

Рабочий пример: предположим, вы хотите загрузить jQuery из CDN с SRI. Найдите сценарий URL, загрузите его (или используйте команду curl для его получения), вставьте байты в калькулятор или используйте `sha384sum` в командной строке, получите дайджест SHA-384 в формате base64 и отформатируйте как `sha384-[base64-digest]`. Вставьте в атрибут целостности тега скрипта. Загрузите страницу и убедитесь, что ошибки консоли не появляются.

Чего это не касается — скрипты, которые изменяются намеренно, и такие сайты, как ToolAcre, которые вообще не загружают внешние скрипты и поэтому нечего прикреплять.

SRI не защищает от всех атак в цепочке поставок. Он защищает от изменения байтов после вычисления дайджеста, но не от того, чтобы дайджест был вычислен из скомпрометированного кода. Если CDN будет скомпрометирован до того, как вы вычислите дайджест, SRI не сможет помочь. Дайджест заслуживает доверия настолько же, насколько и источник, из которого вы его вычислили. Для максимальной уверенности вычисляйте дайджесты из исходного источника (например, выпусков библиотеки на GitHub) и используйте эти дайджесты при загрузке из CDN. Дайджест становится обязательством сопровождающего в процессе выпуска.

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

В этой статье не утверждается инвентаризация внешних скриптов ToolAcre на уровне всего сайта из источников хэша.

Хэш-калькулятор ToolAcre SHA выдает дайджест напрямую в стандартном формате Base64 (как `base64`, выводимый функцией `toBase64()`). Чтобы преобразовать в формат SRI, добавьте имя алгоритма и дефис: `sha256-`, `sha384-` или `sha512-`. Калькулятор не применяет этот префикс автоматически, поскольку хеши появляются во многих контекстах (git, Docker, npm, URL-адреса), где имя алгоритма является отдельным или закодировано по-другому. Граница ясна: калькулятор хеширует UTF-8 вставляемый вами текст, а не файлы или двоичные ключи. Он выводит как шестнадцатеричный, так и base64. Вы выбираете, что использовать, в зависимости от вашего контекста. Для SRI спецификация требует base64. Для git и других инструментов шестнадцатеричный формат является обычным. Для npm и Go используется base64. Выбор кодировки за вами; байты дайджеста одинаковы.

SRI остается одной из немногих криптографических проверок, которые браузер может выполнять на стороне клиента без централизованного управления. Самостоятельное вычисление дайджестов с помощью надежного инструмента, такого как калькулятор SHA ToolAcre, и проверка их на соответствие загруженным ресурсам — это доступный способ защитить веб-сайт от определенных атак в цепочке поставок. Защита настолько хороша, насколько хорош дайджест; пересчитывайте после каждого обновления внешнего ресурса и проверяйте, что браузер загружает скрипт, не отклоняя его.