Как выбрать лимит размера распакованных данных и защититься от архивных бомб

Лимит размера распакованных данных — это максимальный объём, который система разрешает получить при разархивировании файла. Он нужен не для экономии места, а для защиты: без такого ограничения злоумышленник может загрузить крошечный архив, который при распаковке превращается в гигабайты или терабайты данных и исчерпывает диск или память сервера. Главный принцип выбора прост: лимит должен быть заметно больше ожидаемого объёма легитимных файлов, но заведомо меньше ресурсов, потеря которых критична для системы. Ниже разберём, как найти эту границу в вашей ситуации.

Зачем вообще ограничивать распаковку

Сжатие устроено так, что небольшой файл может описывать огромный объём повторяющихся данных. Архив размером в несколько килобайт способен развернуться в гигабайты нулей — такие объекты называют архивными бомбами (zip bomb, tar bomb). Проблема возникает везде, где система автоматически принимает сжатые данные от внешних пользователей:

  • веб-сервисы, принимающие ZIP-архивы с документами, фото или выгрузками;
  • почтовые серверы, распаковывающие вложения для проверки антивирусом;
  • CI/CD-пайплайны, разворачивающие артефакты сборки;
  • API, которые принимают сжатые тела запросов (gzip, deflate);
  • антивирусные сканеры и песочницы, исследующие содержимое архивов.

Последствия отсутствия лимита всегда одинаковы по механике: заполненный диск, исчерпанная оперативная память, зависшие процессы распаковки и недоступность сервиса для обычных пользователей. Восстановление после такой атаки часто сводится к ручной чистке диска и перезапуску сервисов, а в худшем случае — к потере данных соседних приложений, которым не хватило места.

От чего зависит правильное значение лимита

Универсальной цифры не существует. Лимит определяется четырьмя факторами, и пропускать их нельзя ни один:

1. Реальный объём легитимных данных

Начните с измерения. Посмотрите статистику по уже загруженным архивам: медианный и максимальный размер распакованного содержимого. Если 99% пользовательских выгрузок распаковываются в пределах 50 МБ, а единичные большие отчёты достигают 300 МБ, то лимит порядка 500 МБ–1 ГБ закрывает потребности с запасом. Ориентироваться только на среднее значение опасно: оно скрывает «хвост» распределения, и часть честных пользователей начнёт получать ошибки.

2. Свободные ресурсы и их цена

Оцените, сколько одновременных распаковок может идти параллельно, и умножьте лимит на это число. Если десять пользователей одновременно загружают архивы с лимитом 1 ГБ, пиковая потребность может составить около 10 ГБ на диске плюс буферы в памяти. Сравните результат с фактическим свободным местом и учтите, что диск нужен и другим процессам: логам, базе данных, временным файлам. Правило практического минимума: суммарный возможный объём распаковки не должен превышать долю свободного пространства, потеря которой не нарушит работу остальных компонентов.

3. Коэффициент сжатия входных данных

Полезно ограничивать не только итоговый размер, но и отношение «распаковано / сжато». Для текстов, CSV и JSON коэффициент сжатия обычно умеренный, а вот для специально созданных архивов он может достигать тысяч и миллионов раз. Проверка соотношения позволяет отсечь аномалию ещё до того, как система потратила ресурсы на полную распаковку: если загружен файл на 10 КБ, заявленный предел которого — 5 ГБ распакованных данных, это само по себе подозрительный признак.

4. Требования законодательства и регуляторов

В отдельных отраслях (финансы, медицина, госсектор) требования к обработке и хранению данных могут диктовать минимальные объёмы принимаемых файлов. Здесь лимит согласуют не только с техническими возможностями, но и с регуляторными ограничениями — этот аспект стоит уточнить до внедрения, а не после жалоб пользователей.

Типовые ориентиры по сценариям

Приведённые ниже значения — условные отправные точки для обсуждения, а не готовые рекомендации. Их нужно сверить с реальной статистикой вашего сервиса.

Сценарий Характерные данные Условный ориентир лимита
Загрузка документов пользователями PDF, DOCX, сканы Сотни МБ
Импорт выгрузок из других систем CSV, XML, JSON в архиве Единицы ГБ
Резервные копии внутри инфраструктуры Дампы баз, образы Определяется размером источника
Вложения почты перед антивирусом Микс форматов Десятки–сотни МБ на вложение
Артефакты сборки в CI/CD Бинарники, контейнеры По размеру типового билда с запасом

Обратите внимание на последнюю строку: для внутренних процессов, где источник данных контролируете вы сами, лимит может быть жёстко привязан к известному размеру данных, а не выбран «на глаз».

Что ограничивать помимо итогового размера

Один лимит на финальный объём — необходимый, но недостаточный контроль. Надёжная защита строится несколькими слоями:

  • Размер самого архива. Ограничьте загружаемый файл до разумного максимума ещё на уровне веб-сервера или прокси, до передачи в приложение. Это самый дешёвый фильтр.
  • Коэффициент сжатия. Отклоняйте архивы, у которых отношение распакованного объёма к исходному превышает порог, характерный для ваших данных (например, несколько сотен раз).
  • Количество записей и глубина вложенности. Архивы внутри архивов и миллионы мелких файлов ломают файловую систему даже при небольшом суммарном объёме. Ограничьте число элементов и запретите или жёстко лимитируйте вложенные архивы.
  • Распаковка потоково с подсчётом байт. Не полагайтесь на метаданные архива: заголовок может обещать 1 КБ, а реальный поток окажется бесконечным. Считайте фактически прочитанные байты и прерывайте операцию при превышении лимита.
  • Время выполнения. Таймаут на операцию распаковки страхует от случаев, которые не покрыли другие проверки.
  • Изоляция. Распаковывайте в отдельном каталоге с квотой диска или в контейнере с ограниченными ресурсами, чтобы даже ошибка в лимитах не затронула основную систему.

Как настроить лимит: общий порядок действий

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

  1. Соберите статистику по существующим архивам: размеры до и после распаковки, число файлов внутри, коэффициенты сжатия.
  2. Определите перцентиль, который считаете нормой (обычно смотрят 95-й или 99-й), и добавьте запас.
  3. Оцените пиковую параллельность распаковок и сопоставьте суммарный объём со свободными ресурсами.
  4. Выберите поведение при превышении: отклонить файл целиком, распаковать частично с предупреждением или поставить задачу в ручную модерацию.
  5. Настройте технические ограничения: лимит байт при чтении потока, лимит числа записей, глубины вложенности, таймаут.
  6. Добавьте понятное сообщение об ошибке для пользователя с указанием лимита и способом обойти его (например, разбить выгрузку на части).
  7. Протестируйте граничные случаи: архив ровно на лимите, чуть выше него, архив с ложными метаданными, вложенные архивы.
  8. Зафиксируйте мониторинг: сколько запросов отклоняется по лимиту, чтобы вовремя заметить, что порог стал тесным.

Типичные ошибки при выборе лимита

  • Лимит «с потолка». Значение, взятое из чужой статьи без сверки со своей статистикой, либо душит легитимных пользователей, либо оставляет лазейку для атаки.
  • Доверие метаданным архива. Размер, указанный в заголовке ZIP, может не соответствовать действительности. Считать нужно фактически распакованные байты.
  • Учёт только одного файла. Десять архивов по 900 МБ при лимите 1 ГБ каждый дают те же 9 ГБ нагрузки. Нужен также лимит на пользователя, на период времени или глобальная квота.
  • Отсутствие обработки превышения. Если при достижении лимита процесс просто падает, временные файлы остаются на диске. Корректная остановка с очисткой — часть решения.
  • Игнорирование мелких файлов. Миллион файлов по килобайту укладывается в лимит по объёму, но убивает файловую систему количеством операций. Ограничивайте и количество записей.
  • Забытые вложенные архивы. Каждый уровень вложенности может обходить проверки, если они применяются только к внешнему файлу.

Как проверить, что лимит работает

После настройки проведите несколько проверок, не дожидаясь реальной атаки:

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

Если условия разные — действуйте по-разному

  • Данные приходят только от доверенных внутренних систем. Жёсткий лимит можно дополнить белым списком источников; основной акцент — на корректной обработке сбоев, а не на защите от злонамеренных файлов.
  • Файлы загружает широкая аудитория. Комбинируйте все слои защиты: размер архива, коэффициент сжатия, лимит распаковки, число записей, таймаут, изоляцию. Рассмотрите асинхронную обработку с очередью, чтобы пик нагрузки не влиял на интерактивные запросы.
  • Обрабатываются очень большие легитимные архивы. Перейдите от единого лимита к потоковой обработке с квотами: распаковка по частям, промежуточное хранение с политикой очистки, отдельные лимиты на пользователя.
  • Ресурсы сильно ограничены. Занижайте лимит и предлагайте пользователям альтернативу: разбивать выгрузки, использовать форматы без рекурсивного сжатия, отправлять данные по частям через API.

Частые вопросы

Можно ли просто отключить распаковку и принимать только несжатые файлы?

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

Какой коэффициент сжатия считать подозрительным?

Для большинства рабочих данных (документы, таблицы, код) коэффициент редко превышает десятки раз. Значения в тысячи и более раз характерны для искусственно созданных архивов и заслуживают отдельной проверки, хотя сами по себе не доказывают злого умысла.

Нужно ли ограничивать распаковку gzip в HTTP-запросах?

Да, тот же принцип применим: тело запроса, сжатое клиентом, распаковывается сервером, и без лимита это вектор той же атаки. Большинство веб-серверов и фреймворков позволяют задать максимальный размер распакованного тела — проверьте настройку своего стека.

Что делать, если легитимные пользователи начали упираться в лимит?

Сначала посмотрите мониторинг отклонений и статистику размеров: возможно, выросла доля больших выгрузок. Затем либо поднимите лимит с пересчётом ресурсного запаса, либо предложите альтернативный канал для крупных данных, например разбивку на части.

Практический вывод

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

PEFile.ru