Научиться находить уязвимости в реальном коде, формулировать 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) | Данные | High | Имея userId можно смотреть чужие данные |
| Данные о сессиях (время входа/выхода) | Данные | Low | Тамперинг аналитики входа/выхода |
| Файловая система сервера | Инфраструктура | High | Path traversal |
| Внутренняя сеть / метаданные окружения | Инфраструктура | High | SSRF moment |
Вопрос для размышления: какие из активов наиболее критичны и почему? (внутренняя сеть)
Проведите базовое моделирование угроз по методологии STRIDE:
| Категория угрозы | Расшифровка | Применимо к этому приложению? |
|---|---|---|
| Spoofing | Подмена идентификации | Да. Источник - внешний. Все эндпоинты. |
| Tampering | Модификация данных | Да. Источник - внешний. recordSession, exportData |
| Repudiation | Отказ от авторства | Да. Источник - внешний и внутренний. Везде где нет логов. |
| Information Disclosure | Утечка данных | Да. Источник - внешний. totalActivity, userProfile |
| Denial of Service | Отказ в обслуживании | Да. Источник - внешний. register, recordSession |
| Elevation of Privilege | Повышение привилегий | Да. Источник - внешний. notify, exportReport |
Для каждой применимой угрозы укажите:
- Источник угрозы (кто/что может её реализовать)
- Поверхность атаки (через какой эндпоинт/параметр)
- Потенциальный ущерб
Исследуйте каждый эндпоинт вручную — с помощью 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"
# → Что вернёт сервер? Что отрендерит браузер?Данный пример — лишь отправная точка. Исследуйте все эндпоинты самостоятельно.
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-теста для одной из уязвимостей приложения.
Ваша задача — найти остальные, описать их по шаблону выше и написать аналогичные тесты.
| Поле | Значение |
|---|---|
| Компонент | UserAnalyticsController.java (константа класса) |
| Тип | Hardcoded Sensitive Path |
| CWE | CWE-552 |
| CVSS v3.1 | 4.0 MEDIUM (AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |
| Статус | Confirmed |
Описание: Путь экспорта отчётов жёстко задан как /tmp/reports/ — общедоступная директория.
Влияние: Локальный пользователь или процесс может прочитать или изменить отчёты, содержащие пользовательские данные.
Рекомендации по исправлению: Заменить путь на защищённую директорию внутри домашнего каталога приложения, например System.getProperty("user.home") + "/.app/reports".
Шаги воспроизведения:
- Открыть UserAnalyticsController.java:39.
- REPORTS_BASE_DIR = "/tmp/reports/".
- Ожидаемый результат: защищённая директория.
- Фактический результат: общедоступная временная папка.
| Поле | Значение |
|---|---|
| Компонент | /recordSession, /monthlyActivity |
| Тип | Information Disclosure |
| CWE | CWE-209 |
| CVSS v3.1 | 5.3 MEDIUM (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |
| Статус | Confirmed |
Описание: Сообщения исключений напрямую возвращаются клиенту.
Влияние: Атакующий получает информацию о внутренней структуре приложения, что облегчает дальнейшие атаки.
Рекомендации по исправлению: Возвращать общее сообщение об ошибке, а детали логировать на сервере.
Шаги воспроизведения:
- POST /recordSession с loginTime=invalid.
- Ответ содержит "Invalid data: Text 'invalid' could not be parsed...".
- Ожидаемый результат: "Invalid data format".
- Фактический результат: утечка деталей парсинга.
| Поле | Значение |
|---|---|
| Компонент | /exportReport |
| Тип | Path Traversal |
| CWE | CWE-22 |
| CVSS v3.1 | 7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H) |
| Статус | Confirmed |
Описание: filename конкатенируется без проверки, позволяя выход за пределы /tmp/reports/.
Влияние: Атакующий может перезаписать системные файлы или записать вредоносные данные в произвольные директории.
Рекомендации по исправлению: Использовать Paths.get(baseDir).resolve(filename).normalize() и проверять, что результат начинается с baseDir.
Шаги воспроизведения:
- GET /exportReport?userId=x&filename=../../../etc/passwd
- Файл создаётся вне разрешённой директории.
- Ожидаемый результат: отклонение запроса.
- Фактический результат: запись в произвольную локацию.
| Поле | Значение |
|---|---|
| Компонент | /notify |
| Тип | SSRF |
| CWE | CWE-918 |
| CVSS v3.1 | 8.6 HIGH (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N) |
| Статус | Confirmed |
Описание: Сервер выполняет запросы по переданному URL без валидации.
Влияние: Атакующий может сканировать внутреннюю сеть, получать метаданные облака или атаковать внутренние сервисы.
Рекомендации по исправлению: Реализовать allowlist разрешённых доменов и блокировать внутренние IP-адреса (localhost, 169.254.169.254, 10.0.0.0/8 и т.д.).
Шаги воспроизведения:
- POST /notify?userId=x&callbackUrl=http://169.254.169.254/latest/meta-data/
- Сервер обращается к внутреннему адресу.
- Ожидаемый результат: запросы только к разрешённым хостам.
- Фактический результат: доступ к внутренним ресурсам.
| Поле | Значение |
|---|---|
| Компонент | /userProfile |
| Тип | Reflected XSS |
| CWE | CWE-79 |
| CVSS v3.1 | 6.1 MEDIUM (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N) |
| Статус | Suspected |
Описание: Имя пользователя вставляется в HTML без экранирования.
Влияние: Атакующий может выполнить произвольный JavaScript в браузере жертвы, что приводит к краже сессий или фишингу.
Рекомендации по исправлению: Использовать StringEscapeUtils.escapeHtml4() или шаблонизатор (JTE, Thymeleaf) с автоматическим экранированием.
Шаги воспроизведения:
- Зарегистрировать пользователя с именем: <script>alert(1)</script>
- Открыть /userProfile?userId=...
- Ожидаемый результат: отображение как текст.
- Фактический результат: выполнение скрипта.
- OWASP Top 10
- CWE List
- CVSS v3.1 Calculator
- Semgrep Registry — готовые правила для Java
- PortSwigger Web Security Academy — интерактивные материалы по уязвимостям