Безопасность API: недоделанный интерфейс — дырка в базе
АйТи Фреш
Linux, Docker и DevOps

API без защиты: как чужой скрипт утаскивает всю вашу базу за одну ночь

Автор: , директор ООО «АйТи-Фреш» · · ~11 мин чтения
Механическая рука ночью выносит коробки с карточками через окно склада
API без лимитов и проверок отдаёт базу так же исправно, как своим клиентам

API без проверки прав и лимита запросов — открытый кран, из которого утекает база клиентов. Типовые дыры API, сценарий слива за ночь и что закрыть первым.

API, который проверяет только «залогинен ли человек», — это охранник, который пускает в любую квартиру по факту наличия ключа от подъезда.

Почему API — это не «просто ещё один файл на сервере»

Было время, когда сайт был одной программой. Открыл страницу — увидел ровно то, что разрешено. Сегодня почти любой сервис — это связка интерфейсов: мобильное приложение дёргает один адрес, личный кабинет — другой, партнёр — третий, внутренняя CRM — четвёртый. Каждый адрес — отдельная дверь в вашу базу. На двери может быть замок. А может висеть табличка «заходите». Особенно если дверь ставили под дедлайн в ночь перед релизом.

OWASP API Security Top 10 — открытый перечень десяти самых распространённых категорий уязвимостей именно в API, отдельно от классических дыр веб-страниц. Он существует не для красоты. Он существует потому, что эти атаки типовые и кочуют из проекта в проект без изменений. Злоумышленнику не нужно быть гением. Ему нужен ваш API без проверки прав.

Сломанная авторизация объектов — самая частая дыра

Представьте магазин с личным кабинетом, где заказ открывается по адресу /api/orders/1452. Сервер не проверяет, что заказ 1452 принадлежит тому, кто его запрашивает? Тогда меняем 1452 на 1453 — и перед нами чужой заказ, чужой телефон, чужой адрес доставки. Дальше — цикл от 1 до 100 000. Пара часов. База ваша.

Эту уязвимость называют BOLA — Broken Object Level Authorization. Пропускают её чаще всего. Причина не в тупости разработчиков, а в том, что на тестовом стенде с одним аккаунтом её физически не видно: некого путать с кем. Она вылезает только когда у сервиса есть живые клиенты с живыми данными. То есть в самый неудобный момент.

Гостиничный коридор, где одна карта открывает чужой номер
Сломанная авторизация объектов: сервер проверяет, что вы вошли, но не чей это номер

Слабая аутентификация — ключи под ковриком

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

Рекомендация использовать ключи вместе с OAuth 2.0, а не ключ как единственную защиту, появилась не из вредности. Ключ, который не меняется и не привязан к конкретному действию, рано или поздно оказывается скопирован: в публичный репозиторий, в логи, в архив с резервной копией, который подрядчик унёс на флешке. Я видел ключи от боевой базы в комментариях к коду. Серьёзно.

Болтливые ответы: сервер выдаёт больше, чем спросили

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

Отдельная песня — сообщения об ошибках. Упал запрос — сервер любезно рассказал структуру таблиц, версию СУБД и внутренние пути. Для атакующего это не ошибка. Это карта местности. Поэтому и существует правило: ограничивать объём информации в ответах API, особенно в ошибках.

Rate limiting: без лимита любой API — бесплатный экспорт вашей базы

Нет ограничения на число запросов? Тогда взламывать логику не обязательно. Скрипт перебирает ID заказов, адреса почты, номера лицевых счетов — по одному, тысячу раз в секунду, всю ночь. Утром у кого-то есть ваша база. У вас — счёт за трафик.

Отсутствие rate limiting — это не «недоработка». Это бесплатная подписка на вашу базу данных для всех желающих.

Лимит запросов — это одновременно и защита от перебора, и защита от нагрузочных атак. Один IP, сотня запросов в секунду, никаких последствий — вот рецепт и слива, и падения сервера за один вечер.

Турникет и песочные часы пропускают посылки по одной
Ограничение частоты запросов не даёт выкачать всю базу за ночь

Таблица: пять типовых дыр API и что они дают атакующему

Категория уязвимостиЧто происходит на практикеЧто получает атакующий
Сломанная авторизация объектов (BOLA)Нет проверки, что объект принадлежит пользователюЧужие заказы, профили, документы
Слабая аутентификацияКлюч или токен легко подобрать, украсть, использовать без ограниченийДоступ от имени любого пользователя
Избыточные данные в ответахAPI отдаёт весь объект из базы, а не нужные поляТелефоны, адреса, служебные поля, хеши
Отсутствие rate limitingНет лимита запросов с одного источникаМассовая выгрузка базы перебором ID
SSRF через APIСервер по команде пользователя ходит на произвольные адресаДоступ к внутренней инфраструктуре за периметром

Сценарий: пятница, вечер, доставка

Компания запускает мобильное приложение доставки. Полгода штатной работы: заказы, оплата, пуши. Разработчик, который писал API, давно на другом проекте, документации нет. Пятница, 19:40. В поддержку приходит письмо: «ваши клиенты пишут, что видят чужие заказы и адреса». Начинается разбор. При подмене ID сервер без вопросов отдаёт данные любого клиента. Выключить API нельзя — встанут все текущие доставки. Оставить открытым нельзя даже на час.

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

Что всплывает после утечки

У утечки через API всегда есть второй контур, помимо технического. Обязанность уведомить пострадавших. Претензии клиентов и партнёров. Юристы вместо релиза следующей версии. Неправильная конфигурация и недостаточный контроль доступа к API в реальных инцидентах крупных сервисов приводили именно к массовым утечкам персональных данных — это разбирают в отраслевых обзорах безопасности не первый год. Сервис такси Uber, по открытым публикациям, в разное время сталкивался и с утечкой из-за ключа, оставленного прямо в коде, и с инцидентом, причиной которого называли недостаточный контроль API. Два разных случая, один вывод: одна небрежность в разработке стоит дороже, чем годы аккуратной работы.

А теперь честно про тех, кто такие API сдаёт. Типичный подрядчик пишет код под дедлайн, тестирует на одном аккаунте, получает оплату и исчезает. Проверка прав на уровне объектов в смете не стояла — значит, её и нет. Лимиты запросов? «Нагрузки же пока нет». Ключ в коде? «Потом вынесем». Это не экономия. Это заминированное поле, на которое вы потом выпускаете своих клиентов. И когда рванёт, подрядчик скажет: «ТЗ выполнено». Формально он будет прав.

Инвентаризация API: нельзя защитить то, о чём не знаешь

В компаниях, где интерфейсы появлялись постепенно — для сайта, для приложения, для партнёра, для аналитики — часто никто не скажет, сколько их всего и какие до сих пор живы. Забытый тестовый эндпоинт. Старая версия API, оставленная «на всякий случай». Служебный метод для миграции, который так и не выключили. У этих дверей защиты нет вообще, потому что про них просто забыли.

Инвентаризация API — скучное слово. Но именно с неё начинается любая осмысленная проверка. Список всего, что торчит наружу. Кто это вызывает. Зачем. Что будет, если выключить.

Секреты в коде — отдельная боль

Пароли, токены и ключи прямо в исходниках — одна из самых частых причин утечек. Код живёт долго и путешествует далеко: в публичный репозиторий, в архив для подрядчика, в бэкап на личном ноутбуке уволившегося разработчика. Любой ключ в коде считайте скомпрометированным с момента, когда этот код увидел хотя бы один человек за пределами узкого круга. Не «возможно скомпрометированным». Скомпрометированным.

Ключ в репозитории — это пароль от сейфа, написанный на стене подъезда. Неважно, что подъезд «свой».

Что делаем мы в АйТи Фреш и чем это отличается

Когда мы берём сервер или инфраструктуру на обслуживание, API идёт в первых пунктах проверки, а не в разделе «если останется время». Смотрим, какие интерфейсы открыты наружу. Проверяем, есть ли реальная проверка прав на уровне каждого объекта, а не только «залогинен или нет». Ставим ограничение запросов там, где его не было. Выносим ключи из кода в хранилище секретов.

Главное отличие от типичного подрядчика — мы не уходим после сдачи. Остаёмся на обслуживании и видим аномальный трафик в момент, когда он появился, а не через неделю из жалоб пользователей. Лишних сервисов не выдумываем: обслуживание сервера с регулярным контролем безопасности API у нас начинается от 7 000 ₽/мес. Это дешевле одного разового расследования инцидента. И несопоставимо дешевле компенсаций и репутационного удара после слива.

Чек-лист: минимум, без которого API выпускать нельзя

Если у вас есть API, который делали «быстро, чтобы успеть», и с тех пор к его безопасности никто не возвращался — напишите нам в АйТи Фреш. Проверим, что реально открыто наружу, закроем дыры в проверке прав и возьмём инфраструктуру на постоянное обслуживание. Чтобы следующий инцидент не стал новостью пятничного вечера.

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

API работает только для нашего мобильного приложения. Его можно защищать слабее?

Нет. «Внутренний» API, доступный из интернета для мобильного приложения, доступен любому, кто перехватит трафик или декомпилирует приложение. Это такой же публичный интерфейс, как и остальные. Просто о нём реже думают как о публичном.

Можно переложить безопасность API на готовый API Gateway или фреймворк?

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

Как понять, что через API утечка идёт прямо сейчас?

Косвенные признаки: аномальный рост запросов с одного IP или диапазона, обращения к длинным последовательностям ID за короткое время, резкий рост нагрузки на базу без видимых причин со стороны обычных пользователей. Без логов и мониторинга сравнивать не с чем — и вы узнаете об утечке последними.

Сколько стоит проверить безопасность уже работающего API?

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

Обязателен OAuth 2.0 или хватит простого API-ключа?

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

Старый API точно есть, но никто не знает, кто им пользуется. Что делать?

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

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

© ООО «АйТи-Фреш» · Москва · Все статьи