Зачем Google добавляет while(1); в начало своих JSON-ответов?
Зачем Google добавляет while(1); к JSON-ответам?
Это не баг и не случайность. Google использует эту конструкцию для защиты от атаки типа JSON Hijacking (JSON-угон). Давайте разберёмся, как это работает и почему это необходимо.
Что такое JSON Hijacking?
Раньше, до появления современных стандартов безопасности (CORS, SameSite cookies), злоумышленники могли украсть данные из JSON-ответов, используя тег <script>. Вот как это работало:
- Пользователь залогинен на сайте (например, в почте Google).
- Злоумышленник размещает на своём сайте такой код:
<script>
// Переопределяем конструктор Array
Array = function() {
// Перехватываем данные
};
</script>
<script src="https://mail.google.com/mail/feed/atom"></script>
Браузер выполнял этот скрипт как обычный JavaScript. Если ответ содержал массив в формате JSON, то злоумышленник мог переопределить прототип Array и перехватить данные.
Как while(1); защищает?
Добавляя while(1); в начало ответа, Google превращает JSON в невалидный JavaScript. Если злоумышленник попытается загрузить этот ответ через <script>, выполнение скрипта зависнет в бесконечном цикле, и данные не будут украдены.
При этом легитимные запросы через fetch или XMLHttpRequest всё равно могут получить "сырой" текст ответа, обрезать префикс и распарсить JSON.
Как правильно обрабатывать такие ответы?
Ваш подход с replace рабочий, но лучше использовать более надёжный способ:
fetch('https://example.com/api/data')
.then(response => response.text())
.then(text => {
// Убираем while(1); и любые другие префиксы
const jsonStr = text.replace(/^\)\]\}',?\n?/, '').replace(/^while\(1\);/, '');
try {
const data = JSON.parse(jsonStr);
console.log('Данные:', data);
} catch (e) {
console.error('Ошибка парсинга JSON:', e);
}
});
Обратите внимание: Google иногда использует и другие префиксы, например )]}' (для Google Data API). Лучше использовать универсальное регулярное выражение.
Современная альтернатива
Сейчас, с появлением CORS и SameSite cookies, эта проблема частично решена на уровне браузеров. Однако Google продолжает использовать while(1); для обратной совместимости и дополнительной защиты:
- CORS — запрещает чтение ответа с другого домена, если сервер не разрешил это явно.
- SameSite cookies — не даёт отправлять куки с кросс-доменными запросами.
Но старые браузеры и некоторые специфические сценарии всё ещё уязвимы, поэтому защита остаётся актуальной.
Итог
while(1); — это дешёвый и эффективный способ предотвратить утечку данных через JSON Hijacking. Он гарантирует, что ответ нельзя выполнить как скрипт, но при этом его можно прочитать и обработать программно.
Дополнение: другие способы защиты от JSON Hijacking
Помимо while(1);, существуют и другие методы защиты, которые вы можете встретить в разных API:
- Префикс
)]}'— используется в Google Data API. Работает по тому же принципу: делает ответ невалидным JavaScript. - Обёртка в комментарий — например,
/**/{"data": "value"}. Комментарий не выполняется, но JSON остаётся парсибельным. - Использование POST вместо GET — атака JSON Hijacking возможна только через GET-запросы (через тег
<script>). POST-запросы не могут быть выполнены таким образом.
Если вы разрабатываете своё API, рекомендую:
- Всегда использовать
X-Content-Type-Options: nosniffв заголовках. - Добавлять префикс
)]}'к JSON-ответам (это стало де-факто стандартом). - Проверять заголовок
Content-Typeна сервере — не доверять запросам с неправильным типом.
В современных проектах чаще всего достаточно CORS и правильной настройки кук, но для legacy-систем и максимальной безопасности префикс остаётся хорошей практикой.