Учебник Безопасная разработка (Secure Coding) для начинающих
Практический защитный курс о том, как писать безопасный код. Вы научитесь не доверять вводу, разделять данные и команды, правильно хранить пароли и секреты, грамотно применять криптографию и встраивать проверки безопасности в процесс разработки. Каждую уязвимость разбираем парой «как возникает → как защититься → пример исправления» — концептуально, без боевых эксплойтов, чтобы вы не допускали дыр в своих системах.
Курс «Безопасная разработка (Secure Coding)» состоит из 13 разделов и 48 уроков: Введение: безопасность как часть инженерии, Доверие к вводу: валидация и санитизация, Инъекции: данные не должны становиться кодом, Веб-атаки на клиента: XSS и CSRF, Идентичность и доступ: аутентификация и авторизация, Секреты и криптография на практике, Опасные операции: файлы, данные и зависимости, Зрелость: логи, ошибки, API и тестирование, Моделирование угроз и безопасная архитектура, Безопасность API и микросервисов, Безопасность цепочки поставок ПО, Безопасная облачная разработка и Тестирование безопасности и фаззинг. Уроки идут по порядку — от основ к более сложным темам, в каждом есть объяснение с примерами, а в конце — вопросы для самопроверки. К урокам привязаны задачи с автоматической проверкой: прочитали тему — сразу закрепили её кодом.
Программа курса
1 Введение: безопасность как часть инженерии
- Уязвимость — это баг: зачем нужен secure coding
Почему уязвимости — это обычные баги, сколько стоит дыра в продакшене, что такое shift-left и SDLC безопасности.
- Принципы безопасного проектирования
Минимум привилегий, защита в глубину, fail securely, не доверяй вводу, минимизация поверхности атаки — фундамент безопасного кода.
- Моделирование угроз: думать как защитник
Как при проектировании систематически находить угрозы: активы, границы доверия, STRIDE, ранжирование рисков и контрмеры.
- Безопасные дефолты: по умолчанию закрыто
Почему конфигурация по умолчанию должна быть самой защищённой: deny by default, secure-by-default фреймворки и типичные опасные дефолты.
- Уязвимость — это баг: зачем нужен secure coding
2 Доверие к вводу: валидация и санитизация
- Не доверяй вводу: откуда приходят данные
Любой внешний ввод потенциально враждебен: формы, заголовки, URL, файлы, ответы сервисов. Где проходят границы доверия.
- Allowlist против denylist: правильная валидация
Почему белый список почти всегда лучше чёрного, как описать допустимое, и чем валидация отличается от санитизации.
- Где валидировать: слои и контекст
Валидация на входе против экранирования на выходе, валидация на каждой границе доверия и почему безопасность зависит от контекста использования.
- Не доверяй вводу: откуда приходят данные
3 Инъекции: данные не должны становиться кодом
- Анатомия инъекции: данные против кода
Общий механизм всех инъекций: смешение данных и команд в одном тексте. Почему разделение интерпретатора — универсальная защита.
- SQL-инъекция: параметризация и ORM
Как возникает SQL-инъекция, защита параметризованными запросами и ORM, безопасная работа с динамическими частями запроса.
- Командная инъекция: не вызывайте shell
Как возникает инъекция команд ОС, почему опасен вызов через оболочку и как безопасно запускать внешние процессы массивом аргументов.
- LDAP и NoSQL: тот же принцип, другой синтаксис
Инъекции в LDAP-фильтры и NoSQL-запросы, почему «данные ≠ код» работает и здесь, безопасные билдеры и параметризация.
- Анатомия инъекции: данные против кода
4 Веб-атаки на клиента: XSS и CSRF
- XSS: экранирование вывода в нужном контексте
Типы XSS (хранимый, отражённый, DOM), почему страдает браузер пользователя и как контекстное экранирование вывода закрывает уязвимость.
- innerHTML и CSP: защита в глубину против XSS
Почему innerHTML и подобные API опасны, безопасные альтернативы (textContent), и как Content Security Policy служит вторым рубежом.
- CSRF: токены и SameSite-cookie
Как работает подделка межсайтовых запросов, почему виноваты автоматически отправляемые куки, защита анти-CSRF-токенами и атрибутом SameSite.
- XSS: экранирование вывода в нужном контексте
5 Идентичность и доступ: аутентификация и авторизация
- Хеширование паролей: bcrypt/argon2 и соль
Почему пароли нельзя хранить в открытом виде или под MD5, что такое соль, и зачем нужны медленные алгоритмы bcrypt/argon2.
- Защита входа: перебор, лимиты и 2FA
Как защищать форму входа от перебора и подстановки учёток, зачем нужны лимиты и задержки, нейтральные сообщения и второй фактор.
- Сессии и токены: где хранить и как истекать
Управление сессиями и JWT: где безопасно хранить токен, httpOnly-cookie против localStorage, истечение, отзыв и ротация.
- Авторизация: проверяйте права на сервере, не доверяйте клиенту
Разница аутентификации и авторизации, broken access control и IDOR, проверка прав на сервере на каждый запрос, deny by default.
- Хеширование паролей: bcrypt/argon2 и соль
6 Секреты и криптография на практике
- Управление секретами: не хардкодить и не коммитить
Почему секреты в коде и в репозитории опасны, как выносить их в переменные окружения и хранилища, ротация и принципы доступа.
- Криптография правильно: не изобретайте свою
Почему нельзя писать свою криптографию, выбор проверенных примитивов и режимов, что шифровать, и зачем аутентифицированное шифрование.
- TLS и криптостойкий рандом
Зачем шифровать канал TLS и не отключать проверку сертификата, и почему для безопасности нужен криптостойкий генератор случайных чисел.
- Управление секретами: не хардкодить и не коммитить
7 Опасные операции: файлы, данные и зависимости
- Файлы: path traversal и загрузка
Как ввод в путях ведёт к чтению чужих файлов (path traversal) и как безопасно принимать загружаемые файлы: тип, размер, имя, место хранения.
- Десериализация: опасный разбор данных
Почему десериализация недоверенных данных опасна, разница безопасных и небезопасных форматов, как принимать данные без риска исполнения кода.
- Цепочка поставок: зависимости и lock-файлы
Почему сторонний код — часть вашей поверхности атаки, уязвимые библиотеки и SCA, lock-файлы, обновления и риски supply chain.
- Безопасность памяти: переполнения и почему managed безопаснее
Обзор уязвимостей памяти в C/C++ (переполнение буфера, use-after-free) и почему управляемые языки и Rust устраняют целые классы этих ошибок.
- Файлы: path traversal и загрузка
8 Зрелость: логи, ошибки, API и тестирование
- Логи и ошибки: не раскрывать лишнего
Что нельзя писать в логи (секреты, ПДн), зачем нужен аудит, и почему пользователю показывают generic-ошибку, а детали оставляют в логах.
- Защита API: лимиты, валидация и API Top 10
Особенности безопасности API: rate limiting против перебора и DoS, строгая валидация, авторизация на каждый объект, ключевые риски OWASP API Top 10.
- Тестирование безопасности: SAST, DAST и ревью
Линтеры и SAST на этапе кода, DAST по работающему приложению, что искать на security code review и как встроить проверки в CI.
- Логи и ошибки: не раскрывать лишнего
9 Моделирование угроз и безопасная архитектура
- Моделирование угроз по STRIDE
STRIDE: шесть категорий угроз (Spoofing, Tampering, Repudiation, Information disclosure, DoS, Elevation) и как найти угрозы в дизайне по диаграмме потоков данных.
- Деревья атак и поверхность атаки
Деревья атак (узлы И/ИЛИ) для моделирования путей атаки, минимизация поверхности атаки и явные доверительные границы как способ обрубить пути злоумышленнику.
- Принципы безопасного проектирования
Принципы безопасного дизайна: защита по умолчанию, минимум привилегий, эшелонированная защита, fail securely и экономия механизма с примерами кода.
- Требования безопасности и abuse cases
Требования безопасности рядом с функциональными, abuse/misuse cases и безопасность в Definition of Done — как спроектировать защиту ещё до кода.
- Моделирование угроз по STRIDE
10 Безопасность API и микросервисов
- Безопасное проектирование API
Принципы безопасного API: аутентификация и авторизация на каждом эндпоинте, строгая валидация ввода, версионирование и безопасные дефолты.
- Аутентификация сервис-сервис
Как сервисы доказывают друг другу свою личность: mTLS, токены сервисов, ротация ключей и почему внутренняя сеть — не повод для доверия (zero-trust).
- Секреты в распределённых системах
Где хранить и как раздавать секреты микросервисам: vault-подход, короткоживущие креды, почему секретам не место в коде, образе и переменных окружения по умолчанию.
- Лимиты, устойчивость и защита от злоупотреблений
Rate limiting против злоупотреблений API, таймауты, ретраи и circuit breaker как защита от каскадных отказов и DoS в микросервисной архитектуре.
- Безопасное проектирование API
11 Безопасность цепочки поставок ПО
- Уязвимости в зависимостях
Как известные CVE попадают в проект через библиотеки: lock-файлы, транзитивные зависимости, обновления и автоматическое сканирование SCA.
- Атаки на цепочку: typosquatting и компрометация пакетов
Как вредоносные пакеты попадают в проект: typosquatting, dependency confusion, угон аккаунта мейнтейнера. Защита: пиннинг, проверка имён, приватные реестры.
- SBOM и происхождение артефактов
SBOM (состав ПО), подпись артефактов, уровни SLSA и проверка целостности сборки — как доказать, из чего и как собран ваш релиз.
- Безопасность сборки и CI/CD
Безопасность CI/CD: изоляция сборки, защита секретов в пайплайне, минимальные права раннеров и защита артефакта от внедрения вредоносного кода.
- Уязвимости в зависимостях
12 Безопасная облачная разработка
- Безопасность инфраструктуры как кода
Мисконфиги в Terraform и манифестах, сканирование IaC (Checkov, tfsec, Trivy), безопасные модули и политика как код (OPA, Sentinel) — защитный разбор.
- Безопасные контейнеры в разработке
Минимальные образы и non-root, секреты вне образа, сканирование уязвимостей (Trivy/Grype), подпись образов (Cosign) и SBOM — защитный разбор.
- IAM и наименьшие привилегии в облаке
Роли и политики IAM, борьба с over-permission и wildcard, временные креды вместо долгих ключей, аудит доступа (CloudTrail, Access Analyzer).
- Защита данных в облаке
Шифрование at-rest и in-transit, управление ключами KMS и envelope encryption, классификация данных и защита от утечки через мисконфиг.
- Безопасность инфраструктуры как кода
13 Тестирование безопасности и фаззинг
- SAST, DAST, IAST в разработке
SAST, DAST и IAST: где какой подход ловит уязвимости, интеграция в IDE и CI, разбор находок и борьба с ложными срабатываниями. Защитный взгляд на автоматический анализ.
- Фаззинг: поиск багов случайными входами
Фаззинг: как подача программе искажённых входов находит краши и уязвимости, что такое coverage-guided fuzzing, что и как фаззить. С простой Python-иллюстрацией.
- Тесты безопасности как код
Тесты безопасности как код: юнит- и интеграционные тесты на контроль доступа, валидацию ввода и регрессии уязвимостей, которые ловят дыры на каждом коммите в CI.
- Безопасный жизненный цикл и культура
Secure SDLC: security gates в CI/CD, security champions, обучение, метрики и культура без обвинений — как встроить безопасность в процесс разработки, а не в конец.
- SAST, DAST, IAST в разработке