Экспорт данных из продукта: как не превратить выгрузку в утечку
Что стоит за кнопкой «Скачать всё» — и почему именно здесь теряют миллионы записей
Почему экспорт — это не просто UX-фича
Когда продуктовая команда добавляет кнопку «Выгрузить в CSV» или «Скачать отчёт», она думает об удобстве пользователя. Когда безопасник смотрит на ту же кнопку, он видит легитимный канал массового извлечения данных — с авторизацией, которая часто проверяется только один раз, без ограничений на объём, без логирования и без шифрования на выходе.
Именно эта асимметрия делает функцию экспорта одним из самых недооценённых векторов утечек. В отличие от SQL-инъекции или фишинга, экспорт — это легальное действие: пользователь вошёл в систему, нажал кнопку, получил файл. Никакого взлома не происходит. Поэтому инциденты обнаруживают поздно, а иногда — только после того, как данные уже утекли в публичное пространство.
Эта статья — для CTO, VP Engineering, Tech Lead и AppSec-команд, которые уже сталкивались с вопросом: «А что, если кто-то выгрузит всё?» Мы разберём типичные архитектурные ошибки, реальные сценарии инцидентов, регуляторный контекст и практический фреймворк для безопасного проектирования экспорта.
Почему экспорт — особый случай с точки зрения безопасности
Экспорт — это не один запрос
Обычный API-эндпоинт возвращает объект или коллекцию. Эндпоинт экспорта возвращает весь датасет за период, весь список клиентов, все транзакции — нередко за годы. Одна операция экспорта может эквивалентна миллионам обычных запросов по информационной ёмкости.
При этом в архитектуре многих продуктов защита строится следующим образом: на обычных эндпоинтах стоит постраничная пагинация и проверка прав на каждую запись, а эндпоинт экспорта проверяет только одно — «имеет ли пользователь роль, которой разрешён экспорт» — и отдаёт всё. Это классический пропуск авторизации на уровне объекта (Object Level Authorization), который OWASP фиксирует как топ-1 уязвимость [1].
Поверхность атаки шире, чем кажется
В реальном продукте точек экспорта обычно несколько: кнопка в UI, REST API с параметром format=csv, фоновая задача по расписанию, административная панель с «дампом» для поддержки, интеграция с внешним BI или складом данных. Каждая из этих точек — отдельная поверхность атаки. И далеко не на каждой из них реализованы одинаковые проверки.
Британский NCSC в своём паттерне «Безопасный экспорт данных» описывает именно эту проблему: если контроль реализован только в одной точке, но не на всех путях выхода данных, атака на любой из незащищённых путей даёт полный доступ [7].
Инсайдер использует экспорт иначе, чем внешний атакующий
Внешний атакующий ищет уязвимости. Инсайдер просто нажимает кнопку — ту, которую ему позволяет нажать его роль, — и забирает всё, что разрешено. По данным 2024 Insider Threat Report компании Cybersecurity Insiders, 83% организаций зафиксировали хотя бы один инсайдерский инцидент в прошедшем году [4]. По оценке Mimecast за 2026 год, 42% компаний сообщают о росте числа злонамеренных инсайдов — против 33% в 2024 году, при среднем ущербе от одного инцидента в $13,1 млн [5].
Топ-5 архитектурных ошибок при проектировании экспорта
1. Авторизация на уровне роли без проверки на уровне объекта
Самый распространённый паттерн: «если у тебя роль manager, ты можешь экспортировать». Но не проверяется, экспортировать данные каких именно объектов. В результате менеджер из одной организации может подменить org_id в запросе и получить данные другой.
Именно этот сценарий задокументирован в реальном пентест-кейсе с платформой SaaS: все основные эндпоинты были защищены, но эндпоинт экспорта принимал team_id параметром и не проверял, принадлежит ли этот team_id вызывающему пользователю [8]. Классический IDOR — и классическая ошибка, которую допускают даже опытные команды.
Правило OWASP: авторизация должна проверяться не один раз при входе в функцию, а на каждой операции с каждым объектом. Для экспорта это означает фильтрацию данных на уровне запроса к базе, а не «отдать всё и потом отфильтровать в памяти» [9].
2. Отсутствие ограничений на объём и частоту
Если пользователь может запустить 50 экспортов в час и каждый раз скачивать полную базу — это не только нагрузочная проблема, но и сигнал возможной утечки. Rate limiting для экспорта должен быть жёстче, чем для обычных API-запросов, потому что информационная ёмкость одной операции принципиально выше.
NCSC рекомендует реализовывать rate limiting на уровне пользователя, а не только IP-адреса, и настраивать его с учётом объёма данных, а не только количества запросов [7].
3. Скрытые поля и метаданные в экспортируемом файле
Этот риск часто остаётся в слепой зоне. Когда продукт генерирует Excel или PDF, в файл нередко попадают: служебные идентификаторы, внутренние комментарии, история правок, имена авторов документа, технические метаданные. Пользователь не видит этих полей в интерфейсе — но они есть в файле.
NCSC отдельно описывает эту угрозу как «скрытые данные в документах»: современные форматы файлов содержат множество полей и переменных, большинство из которых скрыты от пользователя и могут нести конфиденциальную информацию о вашей организации или других пользователях [7].
На практике это означает: перед выдачей файла необходимо явно формировать «чистую» версию с только теми полями, которые предназначены для экспорта, а не сериализовывать ORM-объект целиком.
4. Передача без шифрования или в небезопасный канал
Экспорт через HTTP вместо HTTPS, отправка ссылки на скачивание по email без срока действия, хранение временного файла экспорта в публично доступном S3-бакете — всё это реальные паттерны, которые регулярно всплывают в инцидентах.
Утечка AT&T в 2024 году произошла именно через неправильно сконфигурированный S3-бакет с экспортом клиентских данных. Пострадали данные 110 млн действующих и бывших клиентов [10].
NCSC рекомендует как минимум использовать TLS для защиты канала передачи, а в случаях повышенного риска — применять объектное шифрование (шифрование каждого файла для конкретного получателя), чтобы данные оставались защищёнными даже при компрометации канала доставки [7].
5. Экспорт без аудит-лога
Если в вашей системе нет записи «кто, когда, какой экспорт запустил и какой объём данных скачал» — вы не сможете обнаружить утечку постфактум, провести расследование или выполнить требование регулятора по уведомлению об инциденте.
OWASP фиксирует отсутствие логирования и мониторинга как отдельную категорию уязвимостей (A09:2021) и приводит примеры авиационных утечек, которые остались незамеченными именно потому, что журналы не собирались или не анализировались [11]. Для экспорта аудит-лог должен содержать минимум: идентификатор пользователя, временную метку, параметры запроса (фильтры, временной диапазон), размер выгрузки в записях, IP-адрес источника.
Регуляторный контекст: что изменилось
Россия: ФЗ-420 и новые штрафы с 2025 года
С 30 мая 2025 года в России действуют поправки к КоАП в рамках ФЗ-420, существенно ужесточившие ответственность за утечки персональных данных. Теперь размер штрафа зависит от масштаба инцидента: утечка 1–10 тысяч записей обойдётся юрлицу до 5 млн руб., более 100 тысяч записей — до 15 млн руб., а при повторном нарушении предусмотрен оборотный штраф от 1% до 3% от годовой выручки [6]. Для сравнения: за весь 2023 год суммарные штрафы за все инциденты составляли около 3,7 млн рублей [12].
Уголовный кодекс РФ с 11 декабря 2024 года дополнен статьёй 272.1, устанавливающей уголовную ответственность за незаконные использование, передачу и предоставление доступа к персональным данным, полученным незаконно [13].
В первом полугодии 2025 года было зафиксировано 154 случая публикации баз данных российских компаний, общий объём скомпрометированных данных составил около 198,6 млн строк [14]. В этом контексте функция экспорта из продукта — не абстрактный технический риск, а потенциальный источник реального регуляторного штрафа.
GDPR: право на переносимость и его оборотная сторона
Статья 20 GDPR закрепляет право субъекта данных на получение своих персональных данных в машиночитаемом формате. Это делает функцию экспорта юридически обязательной для многих продуктов, работающих с европейскими пользователями. Но та же обязательность означает, что реализовать её нужно безопасно: нельзя ни отказать в праве, ни допустить, чтобы пользователь A получил данные пользователя B [15].
Нарушения GDPR в части безопасности могут обернуться штрафами до 4% от мирового годового оборота или 20 млн евро — в зависимости от того, что больше. British Airways в 2019 году получила штраф £183 млн именно за инцидент, в котором данные 400+ тысяч клиентов утекли через уязвимость в платёжной форме [16].
Архитектурный фреймворк: как спроектировать безопасный экспорт
Безопасный экспорт строится не на одном контроле, а на нескольких слоях, каждый из которых работает независимо.
Слой 1. Авторизация — на уровне каждого объекта
Авторизацию нужно реализовывать не только на вход в функцию экспорта, но и на каждую строку данных, включаемую в выгрузку. Практически это означает: запрос к базе данных всегда содержит условие привязки к идентификатору пользователя или организации, а не только проверку роли в middleware.
Проверяйте, что параметры фильтрации (org_id, team_id, user_id) берутся из аутентифицированного контекста сессии, а не из тела запроса или URL-параметров. Параметры из запроса клиента — это входные данные, которые нельзя доверять без валидации.
OWASP Authorization Cheat Sheet формулирует это как принцип Least Privilege: пользователь должен иметь доступ только к минимально необходимому набору данных, а не ко всему, на что у него есть техническая возможность сослаться [9].
Слой 2. Минимизация данных — экспортируйте только то, что нужно
Перед тем как добавлять поле в экспорт, задайтесь вопросом: зачем оно нужно получателю? Классификация данных по уровню чувствительности — обязательный первый шаг. Персональные данные (ФИО, email, телефон, адрес), финансовые идентификаторы, медицинские записи должны либо маскироваться по умолчанию, либо требовать явного запроса с обоснованием.
Практические приёмы:
- Маскирование полей: показывать
****@example.comвместо полного email, если нет специфической роли с доступом к контактным данным. - Псевдонимизация: заменять прямые идентификаторы (user_id) на внешние ключи, которые нельзя восстановить без дополнительной таблицы соответствий.
- Явный whitelist полей: в коде описать разрешённые для экспорта поля, а не сериализовывать полный объект модели.
GDPR Article 25 («privacy by design and by default») требует, чтобы системы по умолчанию обрабатывали минимально необходимый объём персональных данных — без явного действия со стороны пользователя [15].
Слой 3. Ограничения объёма и частоты
Введите лимиты на уровне продукта:
- Максимальный размер одного экспорта в записях или мегабайтах.
- Rate limiting на уровне пользователя (не IP): например, не более 3 экспортов в час для стандартной роли.
- Запрет на параллельные экспорты одним пользователем.
- Таймаут на ссылки для скачивания (не более 24–48 часов).
Для больших экспортов имеет смысл реализовать асинхронную генерацию с уведомлением по email — это создаёт дополнительный барьер (пользователь должен иметь доступ к почтовому ящику) и даёт время на проверку запроса перед выдачей файла.
Слой 4. Шифрование при передаче и хранении
Минимальный стандарт: TLS 1.2+ для всех каналов передачи, AES-256 для хранения временных файлов экспорта [17].
Для повышенного уровня чувствительности — объектное шифрование: файл шифруется публичным ключом получателя, чтобы даже при компрометации хранилища его нельзя было расшифровать без приватного ключа. NCSC описывает это как технику для «высокорисковых сценариев», когда одного TLS недостаточно [7].
Ссылка на скачивание должна быть одноразовой или иметь ограниченный срок действия — это исключает сценарий, когда ссылка утекла через историю браузера, логи прокси или email-переписку.
Слой 5. Аудит и мониторинг аномалий
Каждый экспорт должен быть записан в неизменяемый аудит-лог с полями: идентификатор пользователя, временная метка, параметры запроса, количество строк в результате, хэш файла, IP-адрес и User-Agent.
Поверх аудита необходим мониторинг аномалий:
- Нетипично большой объём для данного пользователя или роли.
- Экспорт в нерабочее время.
- Серия экспортов за короткий промежуток.
- Первый экспорт данного типа у пользователя, никогда ранее его не запускавшего.
Guardz и другие аналитики по итогам 2025 года отмечают, что misuse легитимных инструментов экспорта и административных функций — одна из главных причин того, что традиционные SIEM пропускают инциденты: действие выглядит как обычная рабочая операция [3].
По данным Proofpoint, небольшая доля сотрудников генерирует подавляющее большинство инцидентов утечки данных, а DLP-инструменты последнего поколения фокусируются именно на поведенческих паттернах пользователей, а не только на контент-фильтрации [18].
Инсайдерская угроза: отдельный сценарий для экспорта
Инсайдерские инциденты с экспортом принципиально отличаются от внешних атак. Внешний злоумышленник обычно использует уязвимость (IDOR, SQLi, отсутствие аутентификации). Инсайдер — это авторизованный пользователь, который делает именно то, что ему разрешено, но с недобросовестным умыслом.
Показательный кейс: в мае 2025 года Coinbase раскрыл инцидент, спровоцированный подкупленными зарубежными контрагентами службы поддержки. Они использовали свой легитимный доступ к клиентским данным, чтобы слить информацию о 69 461 пользователе — имена, контактные данные, частичные номера социального страхования, изображения документов. Итоговый ущерб оценён в $400 млн [19].
Для противодействия инсайдерскому злоупотреблению экспортом необходимы:
- Принцип минимальных привилегий: роль «оператор поддержки» не должна иметь возможности экспортировать данные всех клиентов, только тех, с кем ведётся активный тикет.
- Двойное подтверждение: для экспорта чувствительных данных (медицинская информация, финансовые записи) — требовать одобрения второго сотрудника или руководителя.
- Уведомление при необычном экспорте: автоматическое письмо пользователю о том, что был инициирован экспорт, с возможностью обжаловать, если операция была несанкционированной.
- Периодический аудит прав: кто имеет право на экспорт — и действительно ли это нужно их текущей роли?
Чек-лист для команды: что проверить до релиза
Перед тем как выпускать или обновлять функцию экспорта, проверьте каждый пункт:
Авторизация
- Параметры запроса (org_id, user_id, team_id) берутся из контекста аутентифицированной сессии, а не из тела запроса.
- Запрос к БД фильтрует данные на уровне SQL/ORM, не в памяти после выборки.
- Тест на IDOR: попытка подменить идентификатор в запросе возвращает ошибку, а не чужие данные.
- Нет bypass через служебные / batch-эндпоинты без аналогичных проверок.
Минимизация данных
- Описан явный whitelist полей для каждого типа экспорта.
- Поля с PII (email, phone, address) по умолчанию маскированы или исключены для ролей без явного права.
- Сервисные поля (internal_id, db_sequence, audit_fields) не попадают в экспорт.
- Файл экспорта не содержит скрытых метаданных (автор, история правок, системные комментарии).
Ограничения
- Rate limit на экспорт: не более N запросов в единицу времени на пользователя.
- Максимальный размер выгрузки задан и не может быть обойдён параметрами запроса.
- Ссылки для скачивания имеют срок действия (TTL).
- Большие экспорты генерируются асинхронно, а не в рамках одного HTTP-запроса.
Шифрование и передача
- Все каналы передачи — TLS 1.2+.
- Временные файлы хранятся в изолированном, закрытом хранилище, а не публичном бакете.
- Для критичных данных — объектное шифрование файла.
Аудит и мониторинг
- Каждый экспорт записывается в аудит-лог: кто, когда, что, сколько строк.
- Аудит-лог неизменяемый (append-only или хранится в отдельном защищённом хранилище).
- Настроены алерты на аномальный объём, высокую частоту, нетипичное время.
- Аудит-лог регулярно проверяется командой безопасности.
Ошибки, которые кажутся решениями
«Мы спрятали эндпоинт экспорта, значит, его не найдут»
Security through obscurity — одна из худших стратегий. Эндпоинт обнаруживается через перехват трафика мобильного приложения, изучение JS-бандла или анализ сетевых запросов в DevTools. Единственная защита — авторизация и минимизация данных.
«Мы выдаём токен на скачивание — это достаточно»
Токен без срока действия, без привязки к сессии или IP — это просто ещё один статичный секрет, который можно утащить из логов, прокси или истории браузера. Токен должен быть одноразовым и иметь TTL не более нескольких часов.
«Мы логируем все запросы к API»
Логирование HTTP-запросов и аудит-лог экспорта — разные вещи. Первое фиксирует факт обращения к эндпоинту; второе должно фиксировать контекст: какие данные, в каком объёме, с какими параметрами. Только второй тип лога позволяет провести расследование инцидента.
«Пользователь сам виноват, если поделился файлом»
Это перекладывание ответственности. Ответственность за то, что попало в файл, лежит на продукте. Если в экспорте оказались данные других пользователей или поля, которых там быть не должно, — это ошибка архитектуры, а не пользователя.
Кейс: как ошибка в экспорте превращается в инцидент
Рассмотрим типичный сценарий, который часто встречается в пентест-отчётах и публичных write-up'ах [8]:
Продукт — SaaS-платформа для командной работы. У каждой команды есть team_id. Экспорт данных реализован через эндпоинт POST /api/export с телом запроса {"team_id": "123", "format": "csv"}. Middleware проверяет: «является ли пользователь аутентифицированным и имеет ли роль team_admin?» — да. Запрос передаётся в сервис генерации экспорта, который вытаскивает данные по team_id из тела запроса без дополнительной проверки принадлежности.
Атакующий (или инсайдер из другой команды) меняет team_id с 123 на 456 — и получает полный экспорт данных чужой команды. Ни одной ошибки в логах. Никакого триггера мониторинга.
Решение: team_id должен браться не из запроса, а из контекста аутентифицированного пользователя; запрос к БД должен содержать WHERE team_id = :user_team_id. Всё остальное — входные данные, которым нельзя доверять.
Продуктовый экспорт и AI-кодинг: новый риск
Отдельная тема, которая становится всё актуальнее: экспорт как часть кода, написанного с помощью AI. Когда разработчик просит AI-ассистента «добавить функцию экспорта в CSV», тот, как правило, напишет работающий код. Он пройдёт review как «просто добавили экспорт» — потому что дифф небольшой, функция понятна, и никто не дочитывает, что именно сериализуется.
Именно в этом месте чаще всего пропускают: экспортируется весь ORM-объект целиком вместо явного whitelist полей; параметры фильтрации берутся из пользовательского ввода; нет rate limit'а; нет аудит-лога.
PR с функцией экспорта — один из тех случаев, когда «работает» совсем не означает «безопасно». Именно для таких изменений HighVibe работает как дополнительный слой контроля: анализирует конкретный PR с изменением в логике экспорта, проверяет контекст — что сериализуется, как проверяются права, есть ли логирование, — и даёт команде понятный сигнал до merge, пока изменение ещё можно исправить без последствий.
Будущее: DLP и поведенческий анализ как стандарт
По прогнозу Gartner, к 2027 году 70% CISO крупных предприятий примут консолидированный подход, объединяющий DLP и управление инсайдерскими рисками [20]. Глобальный рынок DLP, по разным оценкам, вырастет с $2,58 млрд в 2024 году до $12,29 млрд к 2033 году при среднегодовом темпе роста около 19% [18].
Важный тренд: современные DLP-системы переходят от контент-фильтрации (искать по ключевым словам) к поведенческому анализу — отслеживать, что именно данный пользователь делал раньше и насколько нынешнее действие отклоняется от нормы. Это особенно критично для экспорта: объём и контент запроса могут быть вполне легитимными, но время, частота или последовательность действий — нет.
Ещё один тренд — обязательный аудит доступа к данным как часть compliance-программы. В российском регуляторном контексте 152-ФЗ в редакции 2025 года фактически требует доказательства того, что утечка была обнаружена и расследована — без аудит-лога это невозможно.
Заключение: экспорт — это не UX, это граница безопасности
Функция экспорта данных — это одна из немногих мест в продукте, где одна операция может стоить миллионы строк персональных данных, десятки миллионов рублей штрафа и репутацию компании. При этом именно она чаще всего проектируется «по остаточному принципу» — как удобная техническая фича, без threat modeling и без явного security review.
Безопасный экспорт строится на системе, а не на одном контроле:
- Авторизация на уровне каждого объекта, а не только на входе в функцию.
- Явный whitelist полей — ничего лишнего в файле.
- Rate limiting и ограничения объёма.
- Шифрование канала и хранилища, TTL для ссылок.
- Неизменяемый аудит-лог и мониторинг аномалий.
Это не сложно. Это несколько часов архитектурной работы до того, как функция попала в production. Гораздо дешевле, чем разбираться с инцидентом после.
Источники
[1] OWASP — «A01:2021 – Broken Access Control» — https://owasp.org/Top10/2021/A01_2021-Broken_Access_Control/
[2] OWASP — «Authorization Cheat Sheet» — https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
[3] Guardz — «Top 10 Data Breaches of 2025 and What Caused Them» — https://guardz.com/blog/top-recent-data-breaches/
[4] Cybersecurity Insiders — «2024 Insider Threat Report» — https://www.helpnetsecurity.com/2025/09/18/gurucul-ai-irm-risk-detection/
[5] Mimecast — «2026 State of Human Risk Report» (данные цитируются по underdefense.com) — https://underdefense.com/blog/dlp-solutions/
[6] Robokassa Blog — «Изменения 152-ФЗ с 1 сентября 2025: чек-лист подготовки» — https://robokassa.com/blog/articles/izmeneniya-v-152-fz-s-1-sentyabrya/
[7] NCSC — «Design Pattern: Safely Exporting Data» — https://www.ncsc.gov.uk/guidance/design-pattern-safely-exporting-data
[8] Dedrknex (Medium) — «From a Simple Export Button to Full Data Exposure — Discovering a Broken Access Control in a SaaS Platform» — https://medium.com/@Dedrknex/from-a-simple-export-button-to-full-data-exposure-discovering-a-broken-access-control-in-a-saas-b29a3141a789
[9] OWASP — «Authorization Cheat Sheet (Least Privilege)» — https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
[10] Kiteworks — «Top 11 Data Breaches of 2024 by Risk Exposure Score (AT&T)» — https://www.kiteworks.com/top-11-data-breaches-2024-risk-score/
[11] OWASP — «A09:2021 – Security Logging and Monitoring Failures» — https://owasp.org/Top10/2021/A09_2021-Security_Logging_and_Monitoring_Failures/
[12] РБК Компании — «Защита персональных данных: ключевые изменения с 30 мая 2025 года» — https://companies.rbc.ru/news/ebVqgdTAqA/zaschita-personalnyih-dannyih-klyuchevyie-izmeneniya-s-30-maya-2025-goda/
[13] Правовест Аудит — «Обработка персональных данных: изменения с 30.05.2025» — https://pravovest-audit.ru/nashi-statii-nalogi-i-buhuchet/izmeneniya-v-obrabotke-personalnykh-dannykh-s-30-maya-2025-goda/
[14] ITSec.ru — «За первое полугодие 2025 было 154 случаев утечек баз данных российских компаний» — https://www.itsec.ru/news/za-pervoye-polugodiye-2025-bilo-154-sluchayev-utechek-baz-dannih-rossiyskih-kompaniy
[15] Wikipedia — «General Data Protection Regulation (GDPR)» — https://en.wikipedia.org/wiki/General_Data_Protection_Regulation
[16] Wikipedia — «GDPR fines and notices (British Airways)» — https://en.wikipedia.org/wiki/GDPR_fines_and_notices
[17] SmartSaaS — «SaaS Data Ownership and Portability» — https://smartsaas.works/blog/post/saas-data-ownership-and-portability-dont-be-a-vendor-hostage/95
[18] Proofpoint — «What Is Data Loss Prevention (DLP)?» — https://www.proofpoint.com/us/threat-reference/dlp
[19] PKWARE — «Data Breaches 2025: Biggest Cybersecurity Incidents (Coinbase)» — https://www.pkware.com/blog/recent-data-breaches
[20] Fortinet / Globe Newswire — «Fortinet Delivers AI-Enhanced Data Protection and Insider Risk Management (Gartner prediction)» — https://markets.financialcontent.com/pennwell.cabling/article/gnwcq-2024-10-30-fortinet-delivers-ai-enhanced-data-protection-and-insider-risk-management