# Практикум по безопасности приложений: 12 лабораторных работ

**Версия:** 2.0
**Назначение:** самостоятельная работа слушателя и методическая опора преподавателя по обоим дням программы.
**Основа:** авторская переработка официального лабника курса «Образовательная лаборатория Kaspersky Academy | Безопасность приложений» и идей, выявленных в групповых работах. Исходные документы подгрупп, персональные данные и метаданные не публикуются; боевые payload-инструкции заменены описанием механики, первопричины и проверяемого исправления.

Маршрут начинается с подготовительной ЛР_0, затем ЛР_1–ЛР_9 покрывают A01–A09:2025, ЛР_10 сохраняет историческую практику SSRF A10:2021, а ЛР_11 закрывает нативную память вне веб-модели. A10:2025 — обработка исключительных ситуаций — рассматривается в лекционном блоке, но отдельной лабораторной в этом наборе не заявлена. Так курс остаётся ориентированным на концепции, а не на инструменты.

## 0. Единые правила безопасности и приёмки

### Разрешённая среда

1. Только локальная машина слушателя: `127.0.0.1` и заранее подготовленные локальные контейнеры.
2. Только изолированная Docker-сеть лабораторной; запрещены `--network host`, внешние URL, корпоративные диапазоны, публичные reverse listeners и реальные cloud metadata endpoints.
3. Только синтетические учётные записи, товары, корзины, отзывы, флаги и файлы.
4. Один запуск — одна учебная сессия. В конце обязательно выполнить reset/cleanup среды.
5. Не переносить запросы, варианты входных данных и приёмы из задания в неучебную систему.
6. Образ Juice Shop преподаватель закрепляет конкретным тегом или digest и записывает его в протокол занятия; задания меняются между релизами, поэтому «latest» как учебный контракт недопустим.

### Что сдаёт слушатель

Каждая работа должна содержать:

1. цель и версию среды;
2. один минимально необходимый запрос/ответ, снимок экрана или иной проверяемый артефакт;
3. модель потока и границу доверия;
4. первопричину — не только наблюдаемый симптом;
5. возможные последствия;
6. конкретное исправление на сервере, в архитектуре или в конфигурации;
7. отрицательный regression test, подтверждающий защиту;
8. процедуру reset и отметку, что использовалась только разрешённая среда.

### Общая рубрика (10 баллов)

| Критерий | Баллы | Что проверяется |
|---|---:|---|
| Корректно определена цель и граница стенда | 1 | Нет внешних адресов/данных; понятен объект проверки. |
| Доказательство факта | 2 | Запрос/ответ или эквивалентный артефакт воспроизводим и минимален. |
| Первопричина и модель угроз | 2 | Объяснены субъект, объект, граница доверия и ошибочный контроль. |
| Исправление | 2 | Мера конкретна, server-side/архитектурна и не сводится к UI-ограничению. |
| Регрессионная проверка | 2 | Описан ожидаемый безопасный ответ/результат после исправления. |
| Качество отчёта и cleanup | 1 | Нет секретов/персональных данных; среда сброшена. |

### Формат занятия (ритм каждой ЛР)

- **Контекст** (5–7 мин): категория риска и реальный сценарий — на презентации.
- **Выполнение** (20–25 мин): по шагам, с фиксацией доказательств.
- **Разбор** (10–12 мин): первопричина → паттерн профилактики → план верификации.

---

## ЛР_0. Инвентаризация активов и границы доверия (подготовительная)

**Приоритет:** P0 · фундамент курса
**Карта:** предшествует OWASP Top 10; формирует модель угроз для всех последующих ЛР.
**Среда:** отдельный локальный OWASP Juice Shop с `NODE_ENV=unsafe`, опубликованный только на `127.0.0.1:3000`.

### Цель

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

### Ход работы

1. Пройти пользовательский путь: каталог → регистрация → вход → корзина → оформление/оплата → About/Contact.
2. Составить инвентарь активов: идентификаторы и роли, сессии и токены, заказы и корзина, платёжные данные, административные функции, файловый раздел, загрузка файлов, API, телеметрия и метрики.
3. Сопоставить точки входа: UI-маршруты, REST-эндпоинты (`/api`, `/rest`), файловые эндпоинты (`/ftp`), всё, что обнаруживается из клиентского JavaScript.
4. Определить границы доверия: браузер ↔ приложение; приложение ↔ база данных; приложение ↔ сторонние сервисы; поток обычного пользователя ↔ поток администратора; приложение ↔ парсеры XML/YAML.
5. Для каждого актива указать влияние на конфиденциальность/целостность/доступность, кто должен иметь доступ, точки входа и приоритет защиты.
6. Выбрать топ-5 критических активов и описать последствия их компрометации.

### Доказательства

Заполненная таблица активов (актив · влияние CIA · кто имеет доступ · точки входа · приоритет), список точек входа по категориям, карта границ доверия, обоснованный топ-5.

### Ключевая формулировка

ЛР_0 не даёт «флага». Её результат — карта, к которой возвращаются все следующие работы: каждая уязвимость затем привязывается к конкретному активу и границе доверия из этой карты.

### Задание со звёздочкой

Отметить на карте, какие границы доверия проверяются на сервере, а какие — только в интерфейсе; предсказать, где именно возникнут дефекты A01, A05 и A06.

---

## ЛР_1. Контроль доступа: вертикальный и горизонтальный (BOLA/IDOR)

**Приоритет:** P0
**Карта:** OWASP Top 10:2025 A01 Broken Access Control; CWE-639, CWE-862, CWE-284.
**Среда:** локальный Juice Shop, две синтетические учебные учётные записи.

### Цель

Отделить управляемый клиентом идентификатор от серверного решения об авторизации объекта и операции. Показать оба измерения: вертикальное (доступ к админ-функции без роли) и горизонтальное (доступ к чужому объекту по его идентификатору).

### Ход работы

1. Войти обычным пользователем; наполнить свою корзину различимыми тестовыми товарами.
2. Часть 1 (вертикаль): из клиентского кода найти административный маршрут; проверить, отдаёт ли сервер административные данные обычному пользователю (например, список пользователей или конфигурацию приложения) без проверки роли.
3. Часть 2 (горизонталь): зафиксировать собственный идентификатор корзины; получить у преподавателя идентификатор второй тестовой корзины (без перебора диапазонов) и инициировать к ней запрос в локальной сессии.
4. Сравнить субъект аутентифицированного запроса и владельца объекта в ответе.
5. Сформулировать правило сервера: «разрешить, если субъект — владелец объекта либо имеет явно разрешённую роль».

### Доказательства

Network-запрос и ответ из локальной среды; несоответствие субъекта и объекта; модель проверки ownership; ожидаемый результат после исправления (`403` или безопасный `404`).

### Первопричина

Отсутствие server-side object-level и function-level авторизации: сервер доверяет идентификаторам и маршрутам, пришедшим от клиента. Изменение идентификатора — способ инициировать запрос, но не корень уязвимости.

### Исправление и регрессия

Проверка авторизации на сервере для каждого объекта и каждой изменяющей операции (deny-by-default); opaque-идентификаторы; middleware авторизации для всех эндпоинтов, включая административные. Отрицательный тест: субъект A не читает и не меняет объект субъекта B.

### Задание со звёздочкой

Построить матрицу «три роли × три операции (read/update/delete)» для объекта «корзина»: где проверяется роль, где владение, как тестируется отказ по умолчанию.

---

## ЛР_2. Устаревший интерфейс и оставленная поверхность атаки

**Приоритет:** P1
**Карта:** OWASP Top 10:2025 A02 Security Misconfiguration; CWE-16, CWE-434, CWE-209.
**Среда:** локальный Juice Shop; форма подачи жалобы (Contact Us → Complain).

### Цель

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

### Ход работы

1. Найти устаревший B2B-эндпоинт загрузки файлов, доступный из формы жалобы.
2. Проверить, отвечает ли он на запрос (например, статусом об устаревании) и какие типы файлов реально принимает, несмотря на заявленный список разрешённых.
3. Дополнительно: обратиться к несуществующему REST-эндпоинту и посмотреть, не раскрывает ли сервер подробности ошибки (стек-трейс, внутренние пути).
4. Зафиксировать, что скрытый/забытый эндпоинт продолжает обрабатывать ввод.

### Доказательства

Ответ устаревшего эндпоинта; пример принятого недопустимого типа либо раскрытой диагностики; вывод о расширении поверхности атаки.

### Первопричина

Неполное удаление устаревшей функциональности и конфигурация «по умолчанию открыто»: эндпоинт остался в маршрутизации, диагностика возвращается пользователю.

### Исправление и регрессия

Полное удаление неиспользуемых эндпоинтов; инвентаризация API-поверхности при каждом релизе; серверная проверка файлов по содержанию (magic bytes), а не по расширению; единообразная обработка ошибок без внутренних деталей; allowlist на шлюзе как последний рубеж. Тест: устаревший маршрут отвечает `404`, недопустимый тип отклонён по содержимому, ошибка не раскрывает внутренностей.

---

## ЛР_3. Уязвимая зависимость и цепочка поставок

**Приоритет:** P1
**Карта:** OWASP Top 10:2025 A03 (риски цепочки поставок ПО); CWE-1104, CWE-937, CWE-22.
**Среда:** локальный Juice Shop; публичный файловый раздел `/ftp`.

### Цель

Связать оставленный артефакт разработки с риском компрометации через известную уязвимость зависимости и показать, зачем нужны SBOM и контроль состава.

### Ход работы

1. Открыть файловый раздел и найти забытую резервную копию манифеста зависимостей (часто защищённую наивной фильтрацией расширения — обход относится к A02/A05 и обсуждается отдельно).
2. По списку зависимостей и версий найти хотя бы одну с известной уязвимостью.
3. Оформить корректное сообщение об уязвимости: библиотека, версия, идентификатор (CVE), характер риска.

### Доказательства

Содержимое манифеста (список версий); одна зависимость с известной уязвимостью и её идентификатор; отчёт-сообщение.

### Первопричина

Отсутствие SBOM, контроля состава и политики зависимостей; артефакты разработки (резервные копии манифеста) попадают в общедоступную область.

### Исправление и регрессия

Генерация SBOM и автоматический SCA в CI (например, `npm audit`, Dependency-Check, Snyk); фиксация версий и allow/deny-листы; SLA на исправление; запрет артефактов разработки в production-образах; чувствительные файлы вне рабочего каталога. Тест: сборка падает при появлении зависимости из deny-листа; резервная копия манифеста недоступна публично.

---

## ЛР_4. Утечка конфиденциальных данных и неподписанный токен

**Приоритет:** P0
**Карта:** OWASP Top 10:2025 A04 Cryptographic Failures (как утечка чувствительных данных и отсутствие проверки подписи); CWE-548, CWE-347, CWE-306.
**Среда:** локальный Juice Shop.

### Цель

Показать две разные ошибки под одной темой: раскрытие внутренних документов из-за отсутствия контроля доступа и приём токена без проверки подписи и алгоритма.

### Ход работы

1. Часть 1: найти публичный файловый раздел с листингом директории; обнаружить внутренние документы (например, помеченные «confidential»); зафиксировать факт доступа без аутентификации.
2. Часть 2: получить обычным пользователем токен приложения; декодировать заголовок и полезную нагрузку; проверить, принимает ли сервер токен с заголовком `alg: none` и модифицированной полезной нагрузкой (без действительной подписи).
3. Сопоставить: раскрытие данных — это контроль доступа и классификация; приём неподписанного токена — это проверка криптографической целостности.

### Доказательства

Листинг раздела и пример внутреннего документа; сравнение оригинального и модифицированного заголовка токена; ответ сервера на модифицированный токен; вывод о двух разных первопричинах.

### Первопричина

(1) Нет контроля доступа и классификации данных: внутренние файлы в публичной области, включён листинг директорий. (2) Сервер не фиксирует список допустимых алгоритмов и не проверяет подпись — принимает `alg: none`.

### Исправление и регрессия

(1) Закрыть файловый раздел аутентификацией, отключить листинг, классифицировать данные и применять политики доступа; шифрование там, где контроль доступа недостаточен. (2) Явный allow-list алгоритмов (`algorithms: ['RS256']`), проверка подписи, `iss`, `aud`, `exp`, `nbf`; библиотеки с безопасными настройками по умолчанию. Тесты: внутренний файл требует аутентификации; токен с `alg: none` и любой подделанной нагрузкой отклоняется.

---

## ЛР_5. Пакет инъекций: SQL-инъекция и XSS

**Приоритет:** P0
**Карта:** OWASP Top 10:2025 A05 Injection; CWE-89 (SQL), CWE-79 (XSS).
**Среда:** локальный Juice Shop; для расширенного XSS — отдельный локальный bWAPP, закреплённый тегом/digest и опубликованный только на `127.0.0.1`.

### Цель

Показать общий принцип инъекций — смешение кода и данных — на двух контекстах: серверном SQL-запросе и клиентском DOM. Научиться доказывать первопричину по контексту, а не по факту «появился alert».

### Ход работы

1. Часть 1 (SQL): на странице входа выполнить один обычный неудачный вход (базовое поведение); затем в поле email передать выданную преподавателем строку, характерную для инъекции; наблюдать, происходит ли обход аутентификации. Объяснить, как ввод меняет условие `WHERE` и как комментарий отсекает проверку пароля.
2. Часть 2 (XSS): в поле поиска проверить, отражается ли ввод в DOM без кодирования; безвредным демонстрационным маркером (без кражи cookie и внешних listener-ов) показать выполнение в контексте страницы.
3. Для расширенного варианта на bWAPP пройти уровни `low → medium → high` и сравнить: отсутствие обработки, наивную обработку кавычек, контекстное output encoding.
4. Назвать 2–3 реальных последствия XSS помимо `alert`.

### Доказательства

SQL: базовое поведение и результат обхода (идентификатор аккаунта в интерфейсе). XSS: пара «отражённый контекст — результат браузера»; для bWAPP — три уровня. Объяснение контекста вывода (текст/атрибут/URL/JavaScript — не смешивать).

### Первопричина

Смешение кода и данных: SQL — конкатенация ввода в запрос вместо параметризации; XSS — вставка ввода в DOM без контекстного кодирования.

### Исправление и регрессия

SQL: параметризованные запросы/ORM-шаблоны, минимальные привилегии учётной записи БД. XSS: контекстное output encoding, `textContent`/безопасный DOM-API вместо `innerHTML`, шаблонизатор с auto-escaping, CSP. `HttpOnly` уменьшает часть последствий, но не устраняет XSS. Тесты: инъекционная строка не обходит вход; демонстрационная строка отображается как текст, а не исполняется.

### Нельзя делать

Не давать инструкцию по отправке cookie на внешний сервер; не использовать реальную сессию, корпоративный домен или внешний listener; не заявлять, что `HttpOnly` устраняет XSS.

### Задание со звёздочкой

Написать и протестировать серверный фикс (например, контекстное кодирование в шаблоне) и показать безопасный обход наивного blacklist (регистр, событийные атрибуты) с DOM-маркером вместо кражи данных.

---

## ЛР_6. Небезопасное проектирование: инвариант корзины

**Приоритет:** P1
**Карта:** OWASP Top 10:2025 A06 Insecure Design; CWE-20, CWE-840, CWE-1284.
**Среда:** локальный Juice Shop, синтетическая корзина.

### Цель

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

### Ход работы

1. Создать одну учебную позицию корзины (дорогой товар для наглядности).
2. Зафиксировать корректный запрос изменения количества.
3. В локальной среде передать отрицательное количество в контролируемом запросе к API.
4. Сформулировать инвариант: `quantity` — натуральное число в допустимом диапазоне; уточнить верхнюю границу и поведение при отсутствии товара.
5. Описать последствия для цены, остатков, возвратов, отчётности и смежных транзакций (в учебном приложении отрицательный итог может привести к зачислению вместо списания).

### Доказательства

Корректный и модифицированный запросы; итог с нарушенным инвариантом; предложенные уровни исправления.

### Первопричина

Отсутствие серверной валидации и доменного инварианта: клиентский интерфейс запрещает отрицательное значение, но серверный API принимает любое целое.

### Исправление и регрессия

Три уровня: валидация входа (`quantity >= 1`, только целые); проверка в доменной модели/сервисе (итог заказа `>= 0`, списание только положительными суммами); ограничение в БД (`CHECK quantity >= 1`); денежные типы `decimal` и централизованный расчёт цен. Тест: отрицательное количество даёт `400` и не меняет состояние.

### Что оценивается

Корректная формулировка инварианта важнее «красивого» запроса. Называть кейс A08 (целостность) неверно: здесь урок — небезопасное проектирование бизнес-правила.

---

## ЛР_7. Сбои аутентификации: слабые и дефолтные учётные данные

**Приоритет:** P1
**Карта:** OWASP Top 10:2025 A07 Authentication Failures; CWE-521, CWE-262, CWE-307.
**Среда:** локальный учебный сервис и одна заранее выданная преподавателем тестовая пара.

### Цель

Понять риск дефолтных и слабых учётных данных и выбрать меры, защищающие жизненный цикл учётной записи без превращения задания в инструкцию по массовому подбору.

### Ход работы

1. Использовать только одну выданную тестовую пару; не перебирать пароли и не менять общий административный аккаунт.
2. Объяснить, почему дефолтный секрет опасен при развёртывании, резервном экземпляре, тестовой среде и повторном использовании.
3. Составить политику устранения: обязательная смена при первом входе, disable до настройки, deny-list утёкших паролей, MFA по риску, ограничение автоматизации, мониторинг и оповещение.
4. Спроектировать проверку, что известный дефолтный пароль больше не принимается.
5. Описать, какие события входа должны попасть в logging/alerting (без раскрытия пароля).

### Доказательства

Формулировка риска; политика устранения; описание регрессионной проверки и событий мониторинга.

### Первопричина

Дефолтный/слабый секрет в среде развёртывания и отсутствие политики смены и обнаружения.

### Исправление и регрессия

Уникальный пароль при развёртывании; смена при первом входе; политика надёжных паролей и проверка по спискам утёкших; блокировка/замедление после серии неудач; MFA для привилегированных учёток; мониторинг аномалий. Тест: известный дефолтный пароль после исправления отвергается; серия неудач ограничивается и попадает в события.

### Нельзя делать

Любой brute force против внешней системы, широкие словари, перебор пользователей, действия с реальными учётными данными.

---

## ЛР_8. Небезопасная десериализация: бомба памяти

**Приоритет:** P0
**Карта:** OWASP Top 10:2025 A08 Software or Data Integrity Failures; CWE-502, CWE-400, CWE-776.
**Среда:** локальный Juice Shop; устаревший путь загрузки файла. Ресурсоёмкий разбор выполнять только в изолированном локальном стенде с лимитами ресурсов.

### Цель

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

### Ход работы

1. Убедиться, что устаревший путь загрузки принимает структурированный файл (например, YAML/XML).
2. Подготовить в изолированном стенде файл с рекурсивно ссылающимися алиасами (структура «billion laughs»); загрузить его через устаревший путь.
3. Наблюдать критерий успешности: временная недоступность/замедление сервиса при коротком времени обработки (в учебном приложении — характерная задержка и сообщение о временной недоступности).
4. Связать поведение с уязвимой версией библиотеки-парсера, которая безусловно разворачивает алиасы без ограничения глубины и памяти.

### Доказательства

Факт загрузки через устаревший путь; наблюдаемое замедление/недоступность; версия уязвимой библиотеки-парсера; вывод о механике рекурсивного расширения.

### Первопричина

Десериализация недоверенного структурированного входа без ограничений; парсер без защиты от рекурсивных алиасов (`maxAliasCount`), без лимитов глубины, размера и памяти.

### Исправление и регрессия

Обновить парсер до версии с защитой от рекурсивных алиасов; использовать безопасный режим загрузки без поддержки алиасов; ограничить размер файла, глубину вложенности, время и память; изолировать рискованные парсеры в отдельном процессе с лимитами (cgroups/worker threads); мониторить всплески задержек; удалить устаревший путь загрузки полностью. Тест: файл с рекурсивными алиасами отклоняется/обрабатывается в пределах лимитов, сервис остаётся доступным.

### Нельзя делать

Запускать ресурсоёмкий разбор против внешнего сервиса; использовать структуру как «универсальный payload». Только изолированный стенд с лимитами.

---

## ЛР_9. Сбои логирования, alerting и открытые метрики

**Приоритет:** P1
**Карта:** OWASP Top 10:2025 A09 Security Logging & Alerting Failures; CWE-778, CWE-532, CWE-200.
**Среда:** локальный Juice Shop.

### Цель

Показать логирование как измеримый обнаруживающий контроль, а не набор записей; и что открытые метрики и секреты в клиентском коде расширяют разведку атакующего.

### Ход работы

1. Часть 1: проверить, доступен ли эндпоинт метрик (типовой путь `/metrics`) без аутентификации и какие внутренние детали он раскрывает (версии, счётчики, маршруты, названия внутренних задач, системная информация).
2. Часть 2: проверить клиентский код на предмет жёстко закодированных тестовых учётных данных или ключей; объяснить, почему клиентский код всегда доступен атакующему.
3. Спроектировать «карточку события» безопасности: какие события логируются, какие поля, как защищена целостность, кто реагирует и по какому порогу.

### Доказательства

Ответ эндпоинта метрик и перечень раскрытых деталей; факт наличия секрета в клиентском коде (без публикации самого секрета); проект набора событий и полей.

### Первопричина

Эндпоинт наблюдаемости открыт без аутентификации; секрет оставлен в клиентском коде; логи без корреляции, владельца реакции и порога — не образуют контроль. Много логов без alerting — не мониторинг.

### Исправление и регрессия

Закрыть метрики аутентификацией/сегментацией сети (reverse proxy, allowlist источника); очистить чувствительные метки; события с корреляционным идентификатором, временем, субъектом, объектом, результатом и источником; alerting с порогами и владельцем; никогда не писать в лог пароли, токены, ключи и лишние персональные данные; сканеры секретов в CI; конфигурация через переменные окружения, а не хардкод. Тест: метрики недоступны без авторизации; известный тестовый секрет удалён; контролируемое событие порождает запись и срабатывание правила.

---

## ЛР_10. SSRF: server-side fetch и граница доверия (дополнительная)

**Приоритет:** P0
**Карта:** OWASP Top 10:2021 A10 Server-Side Request Forgery; CWE-918. В OWASP Top 10:2025 SSRF не маркируется как A10 (A10:2025 — некорректная обработка исключительных ситуаций).
**Среда:** самодостаточный fixture `downloads/day-02/participant-materials/lr-ssrf` — только локальная закрытая Docker-сеть.

### Цель

Доказать, что опасен серверный запрос по адресу, выбранному пользователем, а не сам текст URL. Разработать комбинированную прикладную и сетевую защиту.

### Ход работы

1. Проверить `README.md` стенда: только gateway опубликован на `127.0.0.1`, а уязвимое `app` и `internal` находятся в Docker-сети с признаком `internal: true` без host-порта.
2. Запустить стенд; убедиться, что прямой доступ к внутреннему сервису с хоста невозможен (порт не опубликован).
3. Через намеренно уязвимый учебный endpoint передать заранее заданный URL внутреннего контейнера и получить синтетический маркер `INTERNAL_METADATA`.
4. Нарисовать поток: браузер → gateway → приложение → internal; отметить, что опасный запрос создаёт сервер, а не браузер, и что `127.0.0.1` из контейнера указывает на сам контейнер, а корректный вектор — DNS-имя внутреннего контейнера.
5. Спроектировать исправление: allowlist или отказ от произвольного URL, проверка схемы/хоста/фактического IP после DNS, повторная проверка redirect, timeout/лимиты, egress-изоляция.
6. Сформировать положительный и отрицательные тесты (категории адреса/redirect — только в закрытом стенде).

### Доказательства

Запрос и синтетический ответ внутреннего сервиса; лог внутреннего контейнера; threat model с границей доверия; не менее трёх защит и отрицательная regression-матрица; подтверждение, что тест не обращался к внешней сети.

### Первопричина

Приложение выполняет серверный запрос по адресу, выбранному пользователем, без проверки назначения (confused deputy): нет allowlist, нет блокировки внутренних диапазонов после DNS, нет ограничения схемы и redirect.

### Исправление и регрессия

Allowlist адресатов или архитектура «идентификатор ресурса вместо URL»; проверка фактического IP после DNS с блокировкой loopback/private/link-local; отключение или повторная валидация redirect; лимиты; egress-политика на уровне сети. Тест: запрещённые схемы и внутренние адреса отклоняются, разрешённый позитивный маршрут работает.

### Методическая оговорка

Не обещать зачёт конкретного challenge в определённой версии Juice Shop: сценарий зависит от версии и состояния сессии. Fixture нужен именно для воспроизводимого результата.

### Задание со звёздочкой

Показать, почему blacklist по строке «localhost/127.0.0.1» недостаточен: перечислить альтернативные нотации loopback и внутренних адресов (`[::1]`, `0.0.0.0`, сокращённые и десятичные представления IP, DNS-rebinding как класс) — как аргумент в пользу проверки фактического IP после разрешения имени, а не фильтрации строки. Разбор ведётся на уровне классов адресов, без готовых обходных payload-ов против внешних систем.

---

## ЛР_11. Безопасность памяти: переполнение буфера и выполнение команды

**Приоритет:** P0
**Карта:** вне OWASP Top 10 (веб); тема «Безопасность памяти и риски нативного кода»; CWE-787, CWE-120, CWE-78.
**Среда:** локальная Linux-VM или WSL с `gcc`/`clang` и `make`; исходный код предоставляет преподаватель (уязвимая и исправленная версии).

### Цель

Понять разницу между классической инъекцией команд и выполнением команды, вызванным повреждением памяти; воссоздать эффект на учебном примере и устранить первопричину — отсутствие проверки границ.

### Модель угроз

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

### Ход работы

1. Собрать уязвимую и исправленную версии учебной программы (`make`).
2. Запустить уязвимую версию с нормальным вводом — наблюдать штатное поведение (фиксированная безопасная команда).
3. Подать детерминированный учебный ввод, переполняющий буфер имени и затрагивающий соседний буфер команды; наблюдать, что исполняется подставленная команда (в учебном примере — безобидная диагностическая).
4. Повторить тот же ввод на исправленной версии — убедиться, что подмена не происходит.
5. Объяснить, почему это «инъекция команд», хотя ввод не конкатенируется со строкой команды напрямую.

### Доказательства

Вывод нормального запуска; вывод переполнения на уязвимой версии; вывод того же ввода на исправленной версии (защита сработала); сравнительная таблица «уязвимая vs исправленная».

### Первопричина

Чтение пользовательского ввода без проверки границ (`fgets` с размером больше буфера); линейное расположение полей в структуре — переполнение имени перезаписывает соседнюю команду, которая затем передаётся в `system()`. Усугубляют отключённые защиты компилятора.

### Исправление и регрессия

Читать ввод строго по размеру буфера (`sizeof`); безопасные функции (`strncpy`, `snprintf`) и валидация длины; не размещать чувствительные данные рядом с пользовательским буфером; избегать `system()` — использовать `exec`-семейство с фиксированным массивом аргументов; включить защиты компилятора (`-fstack-protector-strong`, `-D_FORTIFY_SOURCE`, PIE/ASLR, RELRO, NX); в CI — санитайзеры и фаззинг границ. Тест: тот же учебный ввод на исправленной версии всегда запускает только фиксированную безопасную команду.

### Вопросы для обсуждения

- Что является основной уязвимостью: использование `system()` или переполнение буфера? Почему?
- Каков был бы реальный риск, если бы такой код был доступен по сети (демон/служба)?
- Почему hardening-флаги — компенсирующая мера, а не замена устранению первопричины?

---

## Приложение A. Активный SVG и безопасный upload pipeline (в подготовке)

**Приоритет:** P2 · advanced
**Карта:** CWE-434, CWE-79 (при подтверждённом исполнении активного содержимого), CWE-22; A02/A05 по конкретной цепочке.

**Статус.** Задание готовится как отдельный self-contained fixture и не проводится по исходным шагам challenge, зависящим от версии Juice Shop и внешнего домена. В качестве заготовки используется контейнеризованная галерея загрузки из групповой работы: она изолирована, без внешнего домена и без версионной привязки.

**Цель будущего стенда** — показать разницу между приёмом пользовательского файла; определением реального типа и ограничением формата; хранением вне webroot; изолированной растеризацией; выдачей с отдельного origin и `Content-Disposition: attachment`; CSP `object-src 'none'`, `X-Content-Type-Options: nosniff`, лимитами и аудитом.

**Критерии включения в курс:** воспроизводимость в изолированной Docker-сети без внешнего домена; разделённые и безопасно сбрасываемые уязвимая и исправленная версии; отсутствие инструкций, превращающих upload в рабочий внешний XSS-канал; доказательство исправления включает анализ типа, изоляцию origin и negative test.

## Приложение B. Шаблон отчёта слушателя

```text
Лабораторная работа: <номер и название>
Среда: <версия, localhost-порт, дата>

Цель:
Граница разрешённой среды:

Что сделано:
1. ...

Доказательства:
- request/response или иной артефакт:
- скрин/журнал:

Ключевая причина:
Потенциальные последствия:

Исправление / профилактика:
- server-side / архитектура:
- конфигурация / сеть:
- наблюдаемость:

Regression check:
Reset/cleanup:
```

## Приложение C. Нормативные и методические опоры

- ГОСТ Р 56939-2024: применимые требования и процесс безопасной разработки.
- ISO/IEC 27034: управление безопасностью приложений в организационном контексте.
- [NIST SSDF (SP 800-218)](https://csrc.nist.gov/pubs/sp/800/218/final): подготовка, защита, производство, реагирование.
- [OWASP ASVS](https://owasp.org/www-project-application-security-verification-standard/): проверяемые требования приложения.
- [OWASP Top 10:2025](https://owasp.org/Top10/2025/0x00_2025-Introduction/): актуальная карта рисков.
- [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html): защита server-side requests.
- CWE: карта первопричин для трассировки исправления и теста.
