Научиться находить уязвимости в реальном коде, формулировать security test cases, классифицировать проблемы через CWE, оценивать их серьёзность через CVSS и оформлять результаты как профессиональный pentest-отчёт.
Учебное REST API на Javalin (Java) для аналитики пользовательской активности.
| Метод | Путь | Параметры | Описание |
|---|---|---|---|
| POST | /register |
userId, userName |
Регистрация пользователя |
| POST | /recordSession |
userId, loginTime, logoutTime (ISO 8601) |
Запись сессии активности |
| GET | /totalActivity |
userId |
Суммарное время активности (в минутах) |
| GET | /inactiveUsers |
days |
Список неактивных пользователей |
| GET | /monthlyActivity |
userId, month (yyyy-MM) |
Активность по дням за месяц |
| GET | /userProfile |
userId |
HTML-профиль пользователя |
| GET | /exportReport |
userId, filename |
Экспорт отчёта в файл на сервере |
| POST | /notify |
userId, callbackUrl |
Уведомление по webhook |
./gradlew run
# Сервер стартует на http://localhost:7000Перед поиском уязвимостей необходимо понять, что именно защищаем.
Заполните таблицу активов системы:
| Актив | Тип | Ценность | Примечание |
|---|---|---|---|
| Данные пользователей (userId, userName) | Данные | Высокая | userId используется как первичный ключ для доступа ко всем другим данным пользователя. userName может содержать XSS-векторы |
| Данные о сессиях (время входа/выхода) | Данные | Средняя | Поведенческие данные - позволяют анализировать активность, вычислять неактивных пользователей, строить графики активности. При утечке могут раскрыть режим работы пользователя. |
| Файловая система сервера | Инфраструктура | Критическая | Эндпоинт /exportReport принимает параметр filename - прямая угроза Path Traversal. Возможно чтение конфигураций, исходного кода, секретов, SSH-ключей, данных других пользователей. |
| Внутренняя сеть / метаданные окружения | Инфраструктура | Критическая | Эндпоинт /notify принимает callbackUrl - угроза SSRF (Server-Side Request Forgery). Атакующий может сканировать внутреннюю сеть, атаковать внутренние сервисы |
Вопрос для размышления: какие из активов наиболее критичны и почему?
Проведите базовое моделирование угроз по методологии STRIDE:
| Категория угрозы | Расшифровка | Применимо к этому приложению? | |
|---|---|---|---|
| Spoofing | Подмена идентификации | Да | userId передаётся как GET/POST параметр - нет аутентификации, нет сессий, нет токенов. Злоумышленник может подставить любой userId и получить данные другого пользователя. |
| Tampering | Модификация данных | Да | Отсутствует контроль целостности. Через userId в запросах можно модифицировать сессии (/recordSession) или экспортировать отчёты других пользователей (/exportReport?userId=). |
| Repudiation | Отказ от авторства | Да | Нет логирования действий. Невозможно доказать, кто именно создал сессию или запросил отчёт. Атакующий может отрицать свои действия. |
| Information Disclosure | Утечка данных | Да | Множество векторов: Path Traversal (/exportReport?filename=), SSRF (/notify?callbackUrl=), отсутствие ACL на userId, возможные ошибки с выводом stack traces. |
| Denial of Service | Отказ в обслуживании | Да | Нет ограничений на количество запросов, размер данных, сложность запросов. /recordSession может заспамить миллионами сессий. /exportReport может открыть огромные файлы. |
| Elevation of Privilege | Повышение привилегий | Частично | Нет ролевой модели (все пользователи равны). Однако через Path Traversal или SSRF атакующий может получить доступ к файлам сервера -> перейти от «пользователь» к «сервер» / «внутренняя сеть». |
Для каждой применимой угрозы укажите:
- Источник угрозы (кто/что может её реализовать)
- Поверхность атаки (через какой эндпоинт/параметр)
- Потенциальный ущерб
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний неаутентифицированный злоумышленник |
| Поверхность атаки | Все эндпоинты, принимающие userId: /register, /recordSession, /totalActivity, /monthlyActivity, /userProfile, /exportReport, /notify |
| Потенциальный ущерб | Доступ к чужим данным, модификация чужих сессий, экспорт отчётов других пользователей. Любой может представиться любым userId. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник |
| Поверхность атаки | /recordSession (параметры userId, loginTime, logoutTime), /register (повторная регистрация того же userId с другим userName) |
| Потенциальный ущерб | Подмена чужих сессий, искажение аналитики активности, засорение базы данных ложными записями, нарушение целостности отчётности. |
| Поле | Значение |
|---|---|
| Источник угрозы | Любой пользователь (злонамеренный или легальный, желающий скрыть свои действия) |
| Поверхность атаки | Все эндпоинты - отсутствие аудита (логирования запросов с идентификацией) |
| Потенциальный ущерб | Невозможно расследовать инцидент безопасности. Администратор не может определить, кто использовал Path Traversal или SSRF. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник |
| Поверхность атаки | GET /exportReport?userId=any&filename= |
| Потенциальный ущерб | Чтение любых файлов на сервере: /etc/passwd, конфигурационные файлы с паролями БД, исходный код приложения, JWT-секреты, SSH-ключи, переменные окружения. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник |
| Поверхность атаки | POST /notify?userId=any&callbackUrl= |
| Потенциальный ущерб | Сканирование внутренней сети, атаки на внутренние сервисы. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник |
| Поверхность атаки | POST /register (параметр userName), затем GET /userProfile (рендеринг имени без экранирования) |
| Потенциальный ущерб | Выполнение произвольного JavaScript в браузере жертвы: кража сессий, фишинг, подделка запросов от имени пользователя. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник или ботнет |
| Поверхность атаки | Любой эндпоинт, особенно: /recordSession (массовая вставка сессий), /exportReport (чтение огромных файлов), /totalActivity (тяжёлые агрегатные запросы) |
| Потенциальный ущерб | Переполнение базы данных миллионами записей, блокировка CPU/IO, исчерпание памяти, падение сервера, невозможность легальным пользователям получить доступ к приложению. |
| Поле | Значение |
|---|---|
| Источник угрозы | Внешний злоумышленник |
| Поверхность атаки | Path Traversal (/exportReport) -> чтение конфигурационных файлов с паролями/токенами -> доступ к БД или внутренним сервисам. SSRF (/notify) -> доступ к внутренней сети и метаданным облака -> компрометация инфраструктуры. |
| Потенциальный ущерб | Переход от «неаутентифицированный пользователь» к «привилегии сервера», «доступ к базе данных», «контроль над облачной средой». Полный захват приложения и инфраструктуры. |
Исследуйте каждый эндпоинт вручную — с помощью curl, Postman, Burp Suite или браузера.
Что проверять:
- Как приложение обрабатывает неожиданные значения параметров?
- Что происходит при передаче спецсимволов (
<,>,",',/,..)? - Что возвращается в теле ответа при ошибках?
- Что происходит с параметрами-путями к файлам или URL?
- Есть ли ограничения на количество запросов или размер данных?
Пример — начало исследования /userProfile:
# 1. Зарегистрировать тестового пользователя
curl -X POST "http://localhost:7000/register?userId=test&userName=Alice"
# 2. Посмотреть, как отображается профиль
curl "http://localhost:7000/userProfile?userId=test"
# 3. Попробовать имя со спецсимволами
curl -X POST "http://localhost:7000/register?userId=evil&userName=%3Cscript%3Ealert(1)%3C%2Fscript%3E"
curl "http://localhost:7000/userProfile?userId=evil"
# → Что вернёт сервер? Что отрендерит браузер?Данный пример — лишь отправная точка. Исследуйте все эндпоинты самостоятельно.
| № | Эндпоинт | Уязвимость | CWE |
|---|---|---|---|
| 1 | /register + /userProfile |
Stored XSS | CWE-79 |
| 2 | Все эндпоинты | Отсутствие аутентификации | CWE-306 |
| 3 | Все эндпоинты | Отсутствие rate limiting | CWE-770 |
| 4 | /recordSession |
IDOR (Spoofing) | CWE-639 |
| 5 | /totalActivity |
IDOR (Spoofing) | CWE-639 |
| 6 | /monthlyActivity |
IDOR (Spoofing) | CWE-639 |
| 7 | /exportReport |
Path Traversal (запись файлов) | CWE-22 |
| 8 | /exportReport |
Directory Traversal / перезапись файлов | CWE-73 |
| 9 | /notify |
SSRF (Server-Side Request Forgery) | CWE-918 |
| 10 | /notify |
SSRF через file:// протокол (чтение файлов) | CWE-918 |
| 11 | /inactiveUsers |
Information Disclosure (ошибки парсинга) | CWE-209 |
| 12 | /monthlyActivity |
Information Disclosure (ошибки парсинга) | CWE-209 |
| 13 | /recordSession |
Information Disclosure (ошибки парсинга) | CWE-209 |
Semgrep — инструмент статического анализа кода, который ищет паттерны уязвимостей без запуска приложения.
# Linux / macOS (через pip)
pip install semgrep
# macOS (через Homebrew)
brew install semgrep
# Проверка установки
semgrep --version# Перейти в корень проекта
cd /path/to/software_testing_lab_4
# Базовый запуск — встроенные правила для Java
semgrep --config "p/java" src/
# Расширенный запуск — правила безопасности OWASP
semgrep --config "p/owasp-top-ten" src/
# Сохранить отчёт в формате SARIF
semgrep --config "p/java" --sarif -o semgrep-report.sarif src/SARIF (Static Analysis Results Interchange Format) — стандартный формат обмена результатами статического анализа (ISO/IEC 5055). Используется в GitHub Actions, GitLab CI, VS Code и IDE для отображения findings прямо в интерфейсе.
Откройте semgrep-report.sarif и изучите структуру:
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [{
"tool": { "driver": { "name": "Semgrep", "rules": [ ... ] } },
"results": [{
"ruleId": "java.lang.security.audit.xss.no-direct-response-writer",
"level": "warning",
"message": { "text": "..." },
"locations": [{
"physicalLocation": {
"artifactLocation": { "uri": "src/..." },
"region": { "startLine": 42 }
}
}]
}]
}]
}Ключевые поля для отчёта:
| Поле SARIF | Что означает |
|---|---|
ruleId |
Идентификатор правила / уязвимости |
level |
Серьёзность: error, warning, note |
message.text |
Описание проблемы |
locations[].region.startLine |
Строка в исходном коде |
relatedLocations |
Связанные места (data flow) |
- Изучите каждый
findingв выводе и в.sarif-файле - Определите, является ли он реальной уязвимостью или ложным срабатыванием (false positive)
- Для каждого finding сопоставьте
ruleIdс соответствующим CWE - Включите результаты Semgrep в финальный отчёт с пометкой о верификации
Важно: Semgrep — вспомогательный инструмент. Статический анализ не заменяет ручное тестирование. Некоторые уязвимости он найдёт, некоторые — нет.
Для каждой найденной уязвимости заполните карточку по следующему шаблону:
| Поле | Значение |
|---|---|
| Компонент | Эндпоинт или класс, где обнаружена уязвимость |
| Тип | Краткое название (например: Reflected XSS) |
| CWE | CWE-XXX — название |
| CVSS v3.1 | Числовой балл (0.0–10.0) и вектор, например: 7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) |
| Статус | Confirmed / Suspected / False Positive |
Описание:
Что происходит и почему это проблема.
Шаги воспроизведения:
1. ...
2. ...
3. Ожидаемый результат: ...
Фактический результат: ...
Влияние:
Что может сделать атакующий, если воспользуется уязвимостью.
Рекомендации по исправлению:
Конкретные меры: какой метод/библиотеку использовать, какую проверку добавить.
Security Test Case:
@Test
@DisplayName("[SECURITY] ...")
void testName() {
// Arrange
// Act
// Assert — проверить, что уязвимость закрыта
}В качестве образца изучите файл:
src/test/java/ru/itmo/testing/lab4/pentest/XssPentestTest.java
Он демонстрирует структуру pentest-теста для одной из уязвимостей приложения.
Ваша задача — найти остальные, описать их по шаблону выше и написать аналогичные тесты.
- OWASP Top 10
- CWE List
- CVSS v3.1 Calculator
- Semgrep Registry — готовые правила для Java
- PortSwigger Web Security Academy — интерактивные материалы по уязвимостям