Безопасность API интернет-магазина: аутентификация, ограничение запросов, CORS, валидация ввода и защита от уязвимостей

独立站对外 API 的安全不是靠一道 WAF 顶上去,而是五层叠加:认证锁身份、限流压刷接口、CORS 收窄跨域口子、输入验证挡住脏数据、依赖扫描定期清后...

独立站 API 五层安全防线:从身份到数据API security: five layers from identity to data 反直觉:只开 HTTPS 不等于安全——HTTPS 防窃听,不防重放、批量调用与注入Counter-intuitive: HTTPS alone does not stop replay, abuse or injection 防线层Layer 挡住什么Stops 关键阈值 / 动作Bar / action 1 认证1. Auth 匿名调用与冒用身份Anonymous / impersonated calls JWT 2 小时过期,密钥季度轮换JWT 2h expiry, rotate quarterly 2 限流2. Rate limit 刷接口与暴力枚举Scraping / brute force 登录 10 次/分,匿名 60 次/分Login 10/min, anon 60/min 3 CORS3. CORS 恶意站点跨域读数据Cross-origin data theft 白名单来源,禁 *. 全放开Allowlist origins, never * 4 输入验证4. Validation SQL 注入 / XSS / 脏数据Injection / XSS / bad data 白名单校验 + 参数化查询Whitelist + parameterized SQL 5 漏洞扫描5. Scanning 已知后门与过期依赖Known vulns / old deps 每周扫一次,高危 72 小时内修Weekly scan, fix critical in 72h 优先级:输入验证 > 认证 > 限流 > CORS > 定期扫描Priority: validation > auth > rate limit > CORS > scanning WAF 是最后一道补丁,不是第一道防线;先把自己代码写干净WAF is a patch, not the first line; clean code first
Пять слоёв защиты API интернет-магазина: приоритеты и пороги аутентификации, ограничения запросов, CORS, валидации ввода и сканирования уязвимостей

Безопасность API интернет-магазина: аутентификация, ограничение запросов, CORS, валидация ввода и защита от уязвимостей

Сначала вывод: 独立站对外 API 的安全不是靠一道 WAF 顶上去,而是五层叠加:认证锁身份、限流压刷接口、CORS 收窄跨域口子、输入验证挡住脏数据、依赖扫描定期清后门。最常见的误判是”开了 HTTPS 就安全了”——HTTPS 只防窃听,不防重放、不防批量调用、不防 SQL 注入。五层里最该先做的不是 WAF,而是输入验证:它直接决定你的数据库会不会被拖库。

Почему «включённый HTTPS» не равен безопасности API

Многие владельцы сайтов считают HTTPS синонимом безопасности: раз трафик между браузером и сервером зашифрован, значит, с интерфейсом всё в порядке. Это первое заблуждение: HTTPS решает проблему «подслушивания в пути», но не решает проблему «легальную личность используют для флуда», «вредоносный скрипт массово бьёт по вашему эндпоинту входа», «в запрос вставляют SQL и вытаскивают таблицу».

Контринтуитивный вывод здесь такой:Настоящие проблемы интернет-магазинов почти всегда связаны с уязвимостями прикладного уровня, а не транспортного. Слив базы, удаление базы, зафлуженные эндпоинты — в 90% случаев это следствие невалидированного ввода, слабой аутентификации и отсутствия ограничения запросов. WAF отсекает часть известных сигнатур атак, но не закрывает дыры в вашей собственной бизнес-логике. Это совпадает с выводами После взлома сайта: сначала чистите код, потом говорите об усилении защиты.

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

Слой защиты Какие атаки блокирует Типовая реализация Что будет, если пропустить
Сертификация Анонимные вызовы, выдача себя за другого API Key, JWT, OAuth2 Данные из эндпоинта может вытянуть кто угодно
Ограничение запросов Брутфорс, массовый флуд эндпоинтов Скользящее окно по IP/Key Credential stuffing на входе, слив базы
CORS 恶意站点跨域读取数据 Белый список источников Чтение данных третьим сайтом под сессией пользователя
Валидация ввода SQL-инъекции, XSS, запись грязных данных Проверка по белому списку + параметризованные запросы Слив всей базы, перехват сессии через XSS в админке
Сканирование уязвимостей Известные бэкдоры, устаревшие зависимости Сканирование зависимостей + регулярный скан уязвимостей Использование старого плагина с публичным EXP

Аутентификация: как выбрать из трёх способов и как управлять ключами

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

Для авторизации на фронтенде используйте JWT: у токена есть срок действия, по умолчанию 2 часа, после истечения обменивается на новый через refresh token. Для интеграции с внешними системами используйте долгосрочный API Key и передавайте его в заголовке запроса, а не в параметрах URL — URL попадают в логи и историю браузера. OAuth2 нужен только когда требуется «разрешить пользователю авторизовать третью сторону для доступа от его имени». В 90% сценариев одиночного сайта он не нужен и лишь добавляет сложности.

Критерий: если интерфейс обслуживает только ваш собственный фронтенд, достаточно JWT; если его будут вызывать программы партнёров, выдайте отдельный API Key и создавайте ключи отдельно для каждого партнёра, чтобы можно было в любой момент отозвать конкретный. Меняйте ключи раз в квартал, при ротации старый и новый ключи сосуществуют 7 дней, чтобы интеграция партнёра не отвалилась сразу.

Способ авторизации Когда подходит Срок действия токена Ротация / отзыв
Session Cookie Традиционный вход через форму в админку Сессия браузера Недействителен после выхода
JWT Разделение фронтенда и бэкенда, вызовы API с фронтенда Access-токен 2 часа refresh 7 дней, чёрный список на сервере
API Key Внешние системы, Webhook-колбэки Долгосрочный, выдаётся по партнёрам Ротация раз в квартал, можно отозвать отдельно
OAuth2 Стороннее приложение действует от имени пользователя Короткий access + refresh Пользователь может в любой момент отозвать доступ

III. Ограничение частоты запросов: по кому ограничивать и какие пороги задавать

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

Три измерения ограничения складываются: по IP — чтобы один атакующий не забил канал, по аккаунту — чтобы перебор паролей по словарю не крутился бесконечно, по API Key — чтобы программа одного партнёра не вышла из-под контроля. Пороги должны быть конкретными числами; таблица ниже — стартовые значения для типичных интерфейсов одиночного сайта, после запуска их калибруют по реальному трафику.

Пример из практики: Интерфейс входа атакуют перебором. Настройте 10 попыток в минуту по IP и 5 неудачных попыток в минуту по аккаунту; при превышении лимита в течение 5 минут подряд блокируйте IP на 1 час. Это эффективнее простого «блокировать аккаунт после 5 неудачных входов», потому что атакующий пробует один пароль к разным аккаунтам, и порог по одному аккаунту его не остановит. О борьбе со спамом в формах читайте в Надёжность формы запроса— там описаны подходы к защите от спама.

Тип интерфейса Измерение ограничения Стартовый порог Действие при превышении
Вход / восстановление пароля IP + аккаунт 10 раз/минуту Временная блокировка на 1 час
Отправка формы запроса IP 3 раза/минуту Показать капчу
Публичный список товаров IP 60 раз/минуту Вернуть 429
Внешняя интеграция по API API Key QPS по условиям договора 429 + уведомить партнёра
Поиск по сайту Сессия 20 раз/минуту Вернуть 429

IV. CORS: когда включать и в каких пределах

CORS (Cross-Origin Resource Sharing) — это встроенная защита браузера: по умолчанию скрипты вашей страницы не могут читать ответы чужих API с другого домена. Дело не в том, что “включил — и стало небезопасно”, а в том, что “настроил неправильно — и стало небезопасно”. Самая частая ошибка — из лени прописать Access-Control-Allow-Origin: * вместе с Allow-Credentials: true. Это равносильно тому, чтобы распахнуть кросс-доменный доступ всему интернету.

Правило простое: если ваш API вызывается только с вашего собственного фронтенда, в белый список CORS вносите только свой домен (в двух вариантах — с www и без), без *. Если API нужен стороннему фронтенду, добавляйте домены по одному, не используйте размытые шаблоны вроде *.yourdomain.com: стоит кому-то зарегистрировать или взломать поддомен — и он сразу становится вектором атаки.

Публичным API без Cookie (например, списку товаров) учётные данные CORS вообще не нужны: браузер не так строг к простым запросам, а чем меньше настроек — тем меньше поверхностей риска. О том, где проходит граница между учётными данными и соответствием требованиям при передаче данных за рубеж, читайте в разделе Комплаенс-основа для выхода на зарубежные рынки о Cookie и трансграничной передаче данных.

Ситуация Настройка Allow-Origin Allow-Credentials Безопасно?
Вызывается только своим фронтендом Белый список строго по своему домену true (нужна сессия) Безопасность
Публичный API с данными о товарах Не настраивать или * false Безопасность
Из лени написать * + credentials true * true Опасно, нужно исправить
Шаблон *.yourdomain.com Размытое сопоставление true Опасно: взлом поддомена всё ломает
Фронтенды нескольких партнёров Белый список по каждому домену true Безопасно, регулярно чистите лишнее

Пять. Валидация входных данных и защита от уязвимостей: не пускаем грязь на порог

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

SQL-инъекции устраняются параметризованными запросами — не склеивайте SQL-строки вручную. XSS устраняется экранированием вывода: сохраняйте пользовательский контент в базу без экранирования, а при выводе на страницу экранируйте по контексту (правила для HTML, JS и URL различаются). При загрузке файлов ограничьте белый список расширений, переименовывайте файлы и храните их вне веб-каталога. Это базовые пункты OWASP Top 10, никаких “продвинутых приёмов” здесь нет.

Сканирование уязвимостей — в постоянном графике: файлы блокировки зависимостей проверяйте автоматически раз в неделю; при обнаружении критичных уязвимостей (CVE выше 9 баллов) обновляйте или временно отключайте функцию в течение 72 часов; раз в месяц проводите пассивное сканирование всего сайта и по результатам удаляйте устаревшие плагины. Как настроить мониторинг и оповещения, читайте в разделе Мониторинг сайта и оповещения. О компромиссах по безопасности самого стека технологий — в разделе Технологический стек crater.

Мера защиты Как сделать Частота / порог Красная линия
Валидация входных данных Тип + длина + белый список значений Обязательно для каждого API Запрещено проверять только на фронтенде
SQL-инъекции Параметризованные запросы / подготовленные выражения Обязательная проверка на код-ревью Запрет на склейку SQL из строк
XSS Экранирование вывода по контексту Все точки вывода пользовательских данных Запрет на вывод rich text без очистки
Загрузка файлов Белый список расширений + переименование Обязательно для всех эндпоинтов загрузки Запрет на выполнение скриптов в папке загрузок
Сканирование зависимостей на уязвимости Автоматическое сканирование lock-файлов Раз в неделю Критические уязвимости от 9 баллов — исправить за 72 часа

FAQ: частые вопросы

Обязателен ли WAF для безопасности самостоятельного сайта?
Нет. WAF — это последняя заплатка: он ловит известные атаки по базе сигнатур, но не остановит инъекции и обход прав, которые вы сами породили в своей бизнес-логике. Если вы работаете один, сначала закройте первые четыре уровня из пяти: аутентификацию, ограничение частоты запросов, CORS и валидацию входных данных, а уже потом думайте о WAF, встроенном в CDN. Если сделать наоборот, получится хороший замок на окне, которое продувает.
Что выбрать: JWT или API Key?
Зависит от того, кто вызывает. Если ваш фронтенд из браузера обращается к вашему же API — используйте JWT со сроком жизни 2 часа и refresh token. Если к вашему API обращается внешняя система или программа партнёра — используйте долгоживущий API Key в заголовке запроса, выдавайте его отдельно каждому партнёру и отзывайте по отдельности. Не используйте JWT для машинных вызовов и не передавайте долгоживущий API Key в браузер.
Как задать пороги ограничения частоты, чтобы не задеть обычных пользователей?
Начните с разбивки по эндпоинтам: вход — 10 раз в минуту, формы — 3 раза в минуту, публичные списки — 60 раз в минуту. После запуска две недели наблюдайте за реальным трафиком и потом корректируйте. Принцип такой: лучше поставить порог вдвое выше пиковой нагрузки живых людей, чем зажать нормальных пользователей. А для по-настоящему опасных эндпоинтов (вход, восстановление пароля) лучше лишний раз заблокировать, чем ослабить защиту. При превышении сначала возвращайте 429, а при повторных превышениях временно блокируйте IP.
Чем плохо Access-Control-Allow-Origin: * в CORS?
Сам по себе * для публичного API только на чтение не страшен. Но если рядом стоит Allow-Credentials: true, это разрешает любому стороннему сайту читать ваш API с авторизацией пользователя — браузеры прямо запрещают такое опасное сочетание. Правильно указывать в Allow-Origin свой домен точно, в двух вариантах: с www и без www. А для кросс-доменных интеграций добавлять домены в белый список по одному.
Зачем валидировать входные данные на бэкенде, если это уже сделано на фронтенде?
Валидация на фронтенде — только удобство для пользователя, а не граница безопасности. Любой может обойти браузер и обратиться к вашему API скриптом или через Postman — проверки на фронтенде будут полностью пропущены. Бэкенд обязан заново проверять каждый входящий параметр на тип, длину и соответствие белому списку значений, а при несовпадении сразу отклонять запрос. На фронтенде можно показывать меньше подсказок, но на бэкенде нельзя убирать ни одной проверки.
Как часто проводить сканирование на уязвимости?
Сканирование зависимостей — раз в неделю, в CI автоматически. Если находится уязвимость с оценкой CVE выше 9, у вас есть 72 часа на обновление или временное отключение функции. Пассивное сканирование всего сайта — раз в месяц, с упором на устаревшие плагины и известные публичные эксплойты. Не ждите инцидента, чтобы начать сканировать: в одиночку проще всего попасться именно на плагине, который не обновлялся полгода.

В заключение

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

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

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

crater
crater Эксперт Crater

Официальный аккаунт организации · crater Crater

环形山 (Crater) — компания, которая помогает выходить на зарубежные рынки: разработка сайтов на WordPress, Google SEO и комплексный рост в GEO. Мы работаем с умными устройствами, промышленным оборудованием, SaaS и новой энергетикой.

Возможности продуктаБелая книга по методологииОтраслевые отчёты
965篇分享
78статей в базе знаний