Веб-безопасность и OWASP Top 10
Самые распространённые веб-уязвимости с реальными примерами и защиты, которые действительно работают.
За 30 секунд
OWASP Top 10 — широко используемый список самых критичных рисков безопасности веб-приложений; текущая редакция — 2025 года. Большинство реальных взломов происходят из-за короткого списка ошибок: отсутствующих проверок доступа, инъекций, ошибок конфигурации, уязвимых зависимостей и утёкших секретов. Хорошая безопасность — это набор привычек, встроенных в проектирование, код-ревью, конфигурацию и деплой, а не финальный аудит.
Почему я это использую
- Я использую OWASP Top 10 как чек-лист, потому что он покрывает ошибки, которые на самом деле приводят к взломам бизнес-приложений.
- Продукты, которые я строю, работают с платежами, персональными данными и данными tenant'ов, где один баг в контроле доступа превращается в серьёзный инцидент.
- Безопасные настройки по умолчанию во фреймворках, заголовках и на серверах почти бесплатно предотвращают целые классы багов.
- Клиенты и аудиторы всё чаще спрашивают, как устроена безопасность, и ясный, конкретный ответ укрепляет доверие.
Как это работает
01OWASP Top 10 простыми словами
OWASP (Open Worldwide Application Security Project) публикует Top 10 на основе реальных данных об уязвимостях и опросов сообщества. Редакция 2025 года выглядит так: A01 Broken Access Control (пользователи получают доступ к данным или действиям, к которым не должны; SSRF теперь входит в эту категорию); A02 Security Misconfiguration; A03 Software Supply Chain Failures (уязвимые или скомпрометированные зависимости, инструменты сборки и пайплайны); A04 Cryptographic Failures; A05 Injection (SQL, команды, а также XSS); A06 Insecure Design; A07 Authentication Failures; A08 Software or Data Integrity Failures; A09 Security Logging and Alerting Failures; A10 Mishandling of Exceptional Conditions (ошибки, при которых система «открывается» или раскрывает детали). Используйте его для повышения осведомлённости и как чек-лист для ревью, а не как полный стандарт; за детальными требованиями обращайтесь к OWASP Application Security Verification Standard (ASVS) и API Security Top 10 — они идут глубже.
02Broken access control, SSRF и CSRF
Broken access control — самый распространённый серьёзный дефект. Классический пример: GET /api/orders/1043 возвращает любой заказ, потому что код проверяет, что пользователь вошёл в систему, но не что заказ принадлежит ему. Это называется IDOR (insecure direct object reference). Решение — проверять владение или права на каждый запрос на сервере, в идеале через централизованные политики, запрещать по умолчанию и возвращать 404 для объектов, которые пользователю видеть нельзя. Server-side request forgery (SSRF) случается, когда ваш сервер загружает URL, переданный пользователем, например при импорте изображения, а атакующий направляет его на внутренние адреса или эндпоинты облачных метаданных. Разрешайте хосты и схемы по allow-list, резолвьте адреса и блокируйте приватные диапазоны IP, отключайте редиректы. Cross-site request forgery (CSRF) заставляет браузер залогиненного пользователя отправить запрос, меняющий состояние; защищайтесь cookie с SameSite, CSRF-токенами и проверкой заголовка Origin.
- Авторизуйте каждый доступ к объекту на сервере, а не в UI.
- Запрещайте по умолчанию; тестируйте со вторым пользовательским аккаунтом.
- Для загрузки по URL: allow-list, блокировка приватных диапазонов, никаких редиректов.
03Инъекции и XSS
Инъекция происходит, когда пользовательский ввод воспринимается как код. При SQL-инъекции поле поиска, содержащее ' OR 1=1 --, меняет смысл запроса, собранного конкатенацией строк, что приводит к утечке или удалению данных. Решение — параметризованные запросы, где данные передаются отдельно от SQL; их поддерживает любой современный драйвер и ORM. Будьте осторожны с хелперами для сырых запросов и динамическими именами колонок — им нужны allow-list'ы. Тот же принцип применим к командам оболочки, LDAP и шаблонизаторам. Cross-site scripting (XSS) — это инъекция в HTML: атакующий сохраняет скрипт в отзыве или имени профиля, и он выполняется в браузерах других пользователей, крадя сессии или совершая действия. Фреймворки вроде React по умолчанию экранируют вывод; опасные зоны — dangerouslySetInnerHTML, v-html, неэкранированный вывод в Blade и URL в атрибутах href. Санитизируйте rich HTML проверенной библиотекой и добавьте Content Security Policy как второй слой.
import { Pool } from "pg";
const db = new Pool();
// Vulnerable: input becomes part of the SQL text
// db.query("SELECT * FROM users WHERE email = '" + email + "'");
// Safe: input is sent as a parameter, never parsed as SQL
export async function findUser(email: string) {
const { rows } = await db.query(
"SELECT id, email FROM users WHERE email = $1",
[email],
);
return rows[0] ?? null;
}
04Ошибки конфигурации и безопасные заголовки
Многим взломам не нужен хитрый эксплойт: оставленный в продакшене режим отладки, публичный бакет хранилища, пароли администратора по умолчанию, подробные страницы ошибок со стектрейсами, листинг директорий, открытые .env или папка .git, порт базы, открытый в интернет. Предотвращайте это конфигурацией в виде кода, настройками для каждого окружения и проверками в пайплайне деплоя. Заголовки безопасности добавляют защиту на стороне браузера. HTTP Strict Transport Security принудительно включает HTTPS. Content Security Policy (CSP) говорит браузеру, из каких источников разрешены скрипты, стили и изображения, и это блокирует большинство внедрённых скриптов; начните в режиме report-only, затем включите принудительно и предпочитайте nonce или хэши вместо 'unsafe-inline'. X-Content-Type-Options останавливает MIME sniffing, frame-ancestors в CSP предотвращает clickjacking, а Referrer-Policy и Permissions-Policy ограничивают, что утекает и что разрешено. Помечайте cookie как Secure, HttpOnly и SameSite.
# nginx: baseline security headers (adapt CSP sources to your app)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https://cdn.example.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
server_tokens off;
05Секреты, зависимости и цепочка поставок
Секретам (API-ключам, паролям к базе, ключам подписи) место в переменных окружения или менеджере секретов, но никогда — в репозитории, клиентских бандлах, логах или сообщениях об ошибках. Давайте каждому секрету минимально необходимые права, разделяйте их по окружениям и ротируйте по расписанию и сразу же после любой подозрительной утечки; утёкший ключ, который нельзя быстро ротировать, — это дефект дизайна. Добавьте сканирование секретов в репозиторий и CI, чтобы ошибки ловились до push'а. Современные приложения в основном состоят из стороннего кода, поэтому сбои цепочки поставок теперь в первой тройке. Коммитьте lockfile'ы, проводите аудит зависимостей (npm audit, composer audit, Dependabot или Renovate), фиксируйте и ревьюйте CI action'ы, удаляйте неиспользуемые пакеты и с подозрением относитесь к новым пакетам с крошечным числом загрузок или install-скриптами. Держите фреймворки и рантаймы на поддерживаемых версиях.
06Rate limiting, боты, ревью и пентесты
Каждому эндпоинту, которым можно злоупотребить, нужны лимиты: вход, запросы OTP и сброса пароля, поиск, контактные формы, загрузка файлов и публичные API. Ограничивайте частоту по пользователю, IP и API-ключу, со строгими лимитами на аутентификацию; блокируйте или замедляйте аккаунты после повторных неудач и добавляйте CAPTCHA или proof-of-work только там, где злоупотребления реальны. CDN или WAF впереди поглощает объёмные атаки и блокирует известные вредоносные шаблоны. Загрузки требуют отдельного внимания: проверяйте тип по содержимому, а не по расширению, ограничивайте размер, защищайтесь от decompression bomb'ов и отдавайте файлы с отдельного домена или через подписанные ссылки. А затем сделайте безопасность процессом. Проводите threat modeling новых фич («что здесь мог бы сделать злонамеренный tenant?»), включайте пункты о безопасности в код-ревью, запускайте SAST и сканирование зависимостей в CI и заказывайте внешний пентест перед крупными запусками и периодически, исправляя находки по степени серьёзности.
- Строгие лимиты на вход, OTP и сброс пароля.
- Логируйте события безопасности (неудачные входы, отказы в доступе) и алертите на всплески.
- Пентесты находят то, что вы пропустили, но не заменяют безопасных привычек.
Когда применять
- Всегда: каждому веб-приложению и API эти основы нужны с первого релиза.
- Перед запуском фич, которые касаются платежей, персональных данных, загрузок или прав доступа.
- Во время код-ревью и архитектурного ревью новых эндпоинтов.
- Перед внешними аудитами, корпоративными продажами и оценками соответствия.
Когда не стоит
- Не считайте Top 10 полным стандартом; для детальных требований используйте ASVS.
- Не полагайтесь на сокрытие (скрытые URL, отключённая introspection) как на единственную защиту.
- Не изобретайте собственную криптографию или хэширование паролей; используйте проверенные библиотеки.
Альтернативы
- OWASP ASVS
Подробный многоуровневый чек-лист требований безопасности для проверки.
- OWASP API Security Top 10
Сфокусирован на рисках API, таких как авторизация на уровне объектов и потребление ресурсов.
- Управляемый WAF и защита от ботов
Защита на edge, которая блокирует распространённые атаки и вредоносный трафик ещё до того, как он дойдёт до вас.
- Программы bug bounty
Непрерывное внешнее тестирование; лучше всего — после того, как сделаны основы и пентест.
Лучшие практики
- Проверяйте авторизацию на сервере для каждого объекта и действия, запрещая по умолчанию.
- Используйте параметризованные запросы и экранирование фреймворка; санитизируйте любой rich HTML.
- Отправляйте заголовки безопасности, включая принудительную Content Security Policy.
- Держите секреты вне кода, давайте им минимальные права и ротируйте их.
- Автоматизируйте сканирование зависимостей и секретов в CI и держите рантаймы на поддерживаемых версиях.
- Ограничивайте частоту для аутентификации, OTP и эндпоинтов, которыми легко злоупотребить.
- Логируйте события безопасности и проверяйте свою защиту ревью и пентестами.
Частые ошибки
- Прятать кнопку в UI вместо того, чтобы проверять права на сервере.
- Собирать SQL или команды оболочки конкатенацией строк.
- Оставлять в продакшене открытыми режим отладки, стектрейсы или админ-панели.
- Закоммитить секреты в Git и лишь удалить их в одном из следующих коммитов.
- Игнорировать алерты о зависимостях, пока активно эксплуатируемая уязвимость не вызовет аврал.
Глубже
07Пароли, сессии и токены — как положено
Храните пароли с медленным memory-hard хэшем. Password Storage Cheat Sheet от OWASP рекомендует Argon2id минимум с 19 MiB памяти, 2 итерациями и parallelism 1; scrypt — если Argon2id недоступен; bcrypt — только для legacy-систем, с work factor 10 или выше и с учётом ограничения входа в 72 байта. Проверяйте новые пароли по спискам известных утечек, а не навязывайте странные правила состава. Для сессий непрозрачные случайные ID, хранящиеся на сервере, просты и мгновенно отзываемы. Если используете JWT, фиксируйте допустимый алгоритм на сервере (никогда не доверяйте заголовку alg из токена), проверяйте issuer, audience и срок действия, делайте access-токены короткоживущими и ротируйте refresh-токены при каждом использовании, считая повторное использование старого refresh-токена кражей и отзывая всё «семейство». Перевыпускайте ID сессии после логина и смены привилегий, чтобы предотвратить session fixation.
import argon2 from "argon2";
// OWASP minimum: Argon2id, 19 MiB memory, 2 iterations, parallelism 1
export function hashPassword(password: string) {
return argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // KiB
timeCost: 2,
parallelism: 1,
});
}
export function verifyPassword(hash: string, password: string) {
return argon2.verify(hash, password); // parameters are read from the hash
}
08Строгая Content Security Policy и Trusted Types
Политики на allow-list (script-src с множеством CDN-хостов) часто обходятся, потому что один из разрешённых хостов может отдавать JSONP-эндпоинт или старую библиотеку, которой злоумышленник может злоупотребить. Строгая политика опирается на nonce или хэши: сервер генерирует новый случайный nonce для каждого ответа и ставит его на каждый легитимный тег script и в заголовок. Добавление 'strict-dynamic' позволяет выполняться и скриптам, загруженным доверенным скриптом, так что tag manager и бандлеры продолжают работать, а внедрённая разметка без nonce блокируется. Сочетайте это с object-src 'none' и base-uri 'none' или 'self'. Против DOM-based XSS Trusted Types (require-trusted-types-for 'script') заставляет браузер отклонять сырые строки в опасных sink вроде innerHTML и пропускать код через проверенную политику санитизации. Сначала выкатывайте в режиме report-only и исправляйте нарушения.
Content-Security-Policy:
script-src 'nonce-r4nd0mBase64Value' 'strict-dynamic';
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
require-trusted-types-for 'script';
report-to csp-endpoint
09SSRF в деталях: DNS rebinding и облачные метаданные
Блокировать приватные IP в строке URL недостаточно. Злоумышленники используют альтернативные записи (десятичные или IPv6-mapped адреса), редиректы на внутренние хосты и DNS rebinding, когда hostname во время вашей проверки резолвится в публичный IP, а мгновением позже при подключении — в 127.0.0.1 или 169.254.169.254. Надёжная защита резолвит hostname один раз, проверяет каждый полученный адрес по запрещённым диапазонам (loopback, private, link-local, unique local IPv6), затем подключается именно к этому IP, отправляя исходный заголовок Host, и перепроверяет при каждом редиректе либо отключает редиректы. Ещё лучше — пропускать все запросы, инициированные пользователем, через egress-прокси, который централизованно применяет политику и не имеет доступа к внутренним сетям. В AWS требуйте IMDSv2: его session token нужно получать PUT-запросом, что блокирует большинство простых попыток SSRF против учётных данных инстанса.
- Проверяйте резолвленные IP, а не текст URL; привязывайте подключение к ним.
- Блокируйте loopback, RFC 1918, link-local и IPv6 unique-local диапазоны.
- Пропускайте пользовательские запросы через изолированный egress-прокси.
10Cookie, CORS и изоляция в браузере
Атрибуты cookie — дешёвый и сильный слой. Secure и HttpOnly держат сессионные cookie подальше от обычного HTTP и от JavaScript. SameSite=Lax, который в современных браузерах используется по умолчанию, если не указан, блокирует большинство межсайтовых POST; используйте Strict для особо чувствительных cookie, а None; Secure — только когда межсайтовое использование действительно нужно. Префикс __Host- требует Secure, Path=/ и отсутствия атрибута Domain, поэтому скомпрометированный поддомен не сможет перезаписать cookie. CORS часто понимают неправильно: он ослабляет same-origin policy, а не защищает ваш API. Никогда не отражайте произвольные значения Origin вместе с Access-Control-Allow-Credentials: true; держите явный allow-list. Для более сильной изоляции Cross-Origin-Opener-Policy: same-origin отделяет ваше окно от cross-origin попапов, а Cross-Origin-Resource-Policy ограничивает, какие сайты могут встраивать ваши ресурсы.
Set-Cookie: __Host-session=9f1c...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=3600
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Vary: Origin
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Реальные ситуации
API-ключ попал в публичный репозиторий
Проблема
Разработчик закоммитил секретный ключ платёжного провайдера в публичный репозиторий. Через час его удалили следующим коммитом.
Как решить
Считайте ключ скомпрометированным: боты сканируют публичные репозитории в течение минут. Немедленно отзовите или ротируйте ключ в панели провайдера, задеплойте новый ключ через переменные окружения или secrets manager и проверьте логи провайдера на активность с неизвестных IP за время утечки. Затем почистите историю, если репозиторий должен остаться публичным, понимая, что это не отменяет утечку. Добавьте secret scanning с push protection, pre-commit hook и более узкие ограниченные ключи для каждого сервиса, чтобы у будущей утечки был меньший радиус поражения.
IDOR, найденный на пентесте
Проблема
Пентест показывает, что изменение ID счёта в /api/invoices/{id}/pdf позволяет скачивать счета других клиентов. Эндпоинт добавили наспех для мобильного приложения.
Как решить
Сначала исправьте эндпоинт: загружайте счёт запросом, ограниченным аккаунтом текущего пользователя, возвращайте 404, если не найдено, и задеплойте. Затем поищите в кодовой базе тот же паттерн — любой обработчик, загружающий по ID без ограничения области, — и проведите их через политику или scoped repository. Добавьте автоматический набор тестов авторизации, который вызывает каждый эндпоинт от имени второго пользователя и ожидает 404 или 403. Просмотрите access-логи за период существования эндпоинта, чтобы понять, эксплуатировался ли он, и если да, уведомите затронутых клиентов.
Внедрение CSP на существующем сайте
Проблема
На маркетинговом сайте с аналитикой, чат-виджетом и инлайн-скриптами нет CSP. Включить политику за один шаг — значит сломать функциональность.
Как решить
Начните с Content-Security-Policy-Report-Only и эндпоинта для отчётов, используя политику на nonce с 'strict-dynamic'. Добавляйте nonce каждого ответа к легитимным инлайн- и внешним скриптам через фреймворк (это умеют Next.js middleware или серверные шаблоны). Неделю собирайте отчёты, исправьте или удалите нарушающие скрипты и перенесите инлайн-обработчики событий в файлы скриптов. Затем включите применение политики, оставьте отчёты включёнными и добавьте проверку в CI или правило code review для любого нового стороннего скрипта.
Шпаргалка
- Хэширование паролей
Argon2id, m=19 MiB, t=2, p=1 (минимум по OWASP)- Сессионная cookie
__Host-session=...; Path=/; Secure; HttpOnly; SameSite=Lax- Ядро строгой CSP
script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none'- Проверить CSP, ничего не сломав
Content-Security-Policy-Report-Only: ...- Заблокировать DOM XSS sink
require-trusted-types-for 'script'- Аудит зависимостей Node
npm audit --omit=dev- Аудит зависимостей PHP
composer audit- Найти секреты в истории Git
gitleaks detect --source .- Требовать IMDSv2 в AWS
aws ec2 modify-instance-metadata-options --instance-id i-0abc --http-tokens required- Быстро проверить заголовки
curl -sI https://example.com
В моих реальных проектах
- В POS SaaS аутентификация использует JWT с RS256, перепроверяемые на каждый запрос с denylist'ом, 2FA для персонала и операторов и API-ключи с ограниченными правами, режимами live/test, rate limit'ами и ротацией.
- Загружаемые там медиа проверяются по содержимому, защищены от decompression bomb'ов и отдаются через подписанные приватные ссылки, а исходящие вебхуки подписываются HMAC.
- Мой базовый набор для серверов: вход по SSH только по ключам, firewall, разрешающий лишь порты 22, 80 и 443, базы никогда не открыты публично, fail2ban и unattended upgrades, HTTPS везде.
- На платформе зоотоваров поиск ограничен rate limit'ом, а вход в админку использует OTP; в общих пакетах сырые данные карт не попадают в сохраняемое хранилище корзины.
Вопросы и ответы
Q1Какая серьёзная уязвимость встречается в веб-приложениях чаще всего?
Broken access control — первое место в OWASP Top 10. Обычно API проверяет, что пользователь аутентифицирован, но не что ему разрешён доступ к конкретному объекту, так что замена ID в URL возвращает чужой заказ или счёт. Это распространено, потому что аутентификацию за вас делают фреймворки, а ваших бизнес-правил они знать не могут. Я предотвращаю это централизованными политиками авторизации, вызываемыми на каждый запрос, ограничением запросов по пользователю или tenant'у, запретом по умолчанию и возвратом 404 для недоступных объектов, плюс автоматическими тестами, которые со второго аккаунта пытаются получить запрещённый доступ.
Q2Как предотвратить SQL-инъекции?
Никогда не собирать SQL конкатенацией строк с пользовательским вводом. Используйте параметризованные запросы или prepared statements, где текст SQL и значения передаются отдельно, так что ввод не может изменить структуру запроса. ORM и query builder'ы делают это по умолчанию, но их хелперы для сырых запросов и динамические идентификаторы вроде колонок сортировки — именно там баги возвращаются; им нужны allow-list'ы. Для эшелонированной защиты пользователь базы должен иметь только те привилегии, которые нужны приложению, а ошибки не должны раскрывать детали SQL. Код-ревью и статический анализ ловят большую часть оставшихся случаев.
Q3Что такое Content Security Policy и как её внедрять?
CSP — HTTP-заголовок, который говорит браузеру, из каких источников разрешены скрипты, стили, изображения, фреймы и соединения. Если атакующий внедрит тег script, браузер откажется его выполнять, если он не соответствует политике, — это делает CSP сильным вторым слоем защиты от XSS. Я внедряю её постепенно: начинаю с Content-Security-Policy-Report-Only и сборщика отчётов, устраняю нарушения от легитимных источников, затем включаю принудительно. Для inline-скриптов предпочитаю nonce или хэши вместо 'unsafe-inline', добавляю object-src 'none', base-uri 'self' и frame-ancestors против clickjacking и пересматриваю политику при каждом изменении сторонних скриптов.
Q4XSS и CSRF: в чём разница?
XSS (cross-site scripting) означает, что атакующему удаётся запустить свой скрипт внутри вашего сайта, например через неэкранированный комментарий. Этот скрипт выполняется с правами пользователя на вашем origin, так что может читать страницу и отправлять запросы. CSRF (cross-site request forgery) означает, что другой сайт заставляет браузер пользователя отправить запрос на ваш сайт, пользуясь его cookie, не запуская код на вашем origin. XSS предотвращают экранированием вывода, санитизацией и CSP. CSRF — cookie с SameSite, anti-CSRF-токенами и проверкой Origin. Учтите, что XSS обходит защиту от CSRF, потому что скрипт может прочитать токены.
Q5Как вы управляете секретами в проекте?
Секреты никогда не попадают в репозиторий, клиентский бандл или логи. Они живут в переменных окружения, передаваемых при деплое, или, что лучше, в менеджере секретов с контролем доступа и журналом аудита. У каждого окружения свои секреты, у каждого секрета — минимально необходимые права, а ротация — рутинная задокументированная операция. Сканирование секретов работает в pre-commit хуках и в CI. Если секрет утёк, я сначала ротирую его, а потом разбираюсь, потому что удаление из истории Git не поможет, если его уже запушили: кто угодно мог его скопировать.
Q6Что бы вы проверили при быстром ревью безопасности веб-приложения?
Начинаю с контроля доступа: может ли пользователь A добраться до ресурсов пользователя B, поменяв ID, и защищены ли админские эндпоинты на сервере? Затем аутентификация: хэширование паролей, rate limiting на вход и OTP, работа с сессиями и токенами. Затем обработка ввода: параметризованные запросы, экранирование вывода, валидация загрузки файлов и любая загрузка URL на стороне сервера. Дальше конфигурация: режим отладки, страницы ошибок, открытые файлы, заголовки безопасности, CORS и флаги cookie. Потом секреты в репозитории и результаты аудита зависимостей. И наконец, логирование: записываются ли неудачные входы и отказы в доступе и есть ли на них алерты? Это быстро покрывает большую часть Top 10.
Вопросы уровня senior
S1JWT или серверные сессии: что бы вы выбрали и почему?
Для собственного веб-приложения серверные сессии с непрозрачным ID в cookie с префиксом __Host- обычно более безопасный выбор по умолчанию: мгновенный отзыв, маленькие cookie и никаких подводных камней с парсингом токенов. JWT полезны, когда многим сервисам нужно проверять личность без обращения к центральному хранилищу, или для доступа к API третьих сторон. Их цена: для отзыва нужен короткий срок жизни плюс denylist или перепроверка на каждый запрос, работа с алгоритмами и ключами должна быть строгой, а хранение в localStorage открывает их для XSS. Распространённый гибрид — короткоживущие access-токены, порядка минут, с ротируемыми refresh-токенами в HttpOnly cookie и обнаружением повторного использования. Что бы вы ни выбрали, подписывайте асимметричными ключами, когда проверяют несколько сервисов, ротируйте ключи с key ID и логируйте события аутентификации для обнаружения атак.
S2Как встроить безопасность в пайплайн доставки, не замедляя команды?
Автоматизируйте дешёвые и точные проверки, а человеческое внимание оставьте для дизайна. В пайплайне: secret scanning с push protection, аудит зависимостей, который падает только на проблемах высокой критичности с доступным исправлением, SAST, настроенный на небольшой проверенный набор правил, lockfile и закреплённые версии CI actions, а также сканирование образов контейнеров. Блокируйте merge на значимых находках, остальное отправляйте в бэклог с владельцами. Перед написанием кода проводите короткую сессию threat modelling для фич, затрагивающих аутентификацию, платежи, загрузки или границы тенантов. Давайте безопасные настройки по умолчанию в общих библиотеках — scoped repository, HTTP-клиент с защитой от SSRF и middleware для заголовков, — чтобы безопасный путь был лёгким. Компромисс — усилия на настройку и тюнинг: ненастроенные инструменты создают шум, который разработчики привыкают игнорировать.
S3Как бы вы отреагировали на критическую уязвимость, раскрытую в используемой вами зависимости?
Относитесь к этому как к инциденту, где время идёт. Сначала определите подверженность: есть ли уязвимый пакет в продакшен-сборках, в затронутой версии, и достижим ли уязвимый путь кода с входными данными под контролем злоумышленника? Software bill of materials или поиск по lockfile отвечают на первые два вопроса за минуты. Если вы подвержены, смягчайте самым быстрым способом: обновитесь или примените патч либо временную меру — правило WAF, отключение функции или блокировку шаблона ввода. Деплойте через обычный пайплайн, но в ускоренном режиме, и проверьте исправление. Проверьте логи на попытки эксплуатации с момента раскрытия и ротируйте секреты, если было возможно выполнение кода. После этого разберите, почему обнаружение заняло столько времени и поймали бы это раньше инструменты автоматического обновления.
Глоссарий
- IDOR
- Insecure direct object reference: доступ к чужому объекту через изменение идентификатора.
- SSRF
- Server-side request forgery: принуждение сервера запрашивать внутренние или непредусмотренные URL.
- CSRF
- Поддельный межсайтовый запрос, который использует cookie жертвы, чтобы изменить состояние.
- XSS
- Cross-site scripting: скрипт под контролем злоумышленника, выполняющийся на страницах вашего сайта.
- CSP nonce
- Случайное значение для каждого ответа, помечающее, какие скрипты браузеру разрешено выполнять.
- Trusted Types
- Функция браузера, блокирующая сырые строки в опасных DOM sink, если они не прошли через политику.
- Argon2id
- Memory-hard алгоритм хэширования паролей, рекомендованный OWASP для их хранения.
- DNS rebinding
- Приём, при котором hostname во время проверки резолвится в безопасный IP, а позже — во внутренний.
- Атака на цепочку поставок
- Компрометация ПО через его зависимости, инструменты сборки или пайплайн доставки.
Что изучить дальше
Есть идея продукта?Давайте создадим его.
Расскажите о своей идее, продукте или команде. Обычно отвечаю в течение одного рабочего дня.