Введение
Эшелонированная защита (defense in depth) подразумевает использование нескольких уровней контроля одновременно, чтобы одна ошибка не привела к компрометации важного актива. Проверка токена, привязка к локальной сети, права доступа к файлам и логирование — каждый из этих механизмов защищает отдельный аспект одной и той же службы.
В этой лабораторной работе вы укрепите безопасность небольшой службы на Python, которая считывает секретный файл. Вы будете вносить по одному небольшому изменению за раз, запускать службу, тестировать её с помощью curl и проверять, как эти уровни работают вместе.
Начало работы с незащищенным секретом
На этом этапе вы изучите службу и увидите первый уровень контроля: запрос без ожидаемого токена отклоняется, в то время как запрос с токеном проходит успешно. Эшелонированная защита начинается с проверки того, что уже защищено, а что требует дополнительного уровня безопасности.
Перейдите в каталог проекта:
cd /home/labex/project
Выведите список подготовленных файлов:
ls -l
Вы должны увидеть secret_service.py, secret.txt и service-check.py.
Запустите службу в фоновом режиме. Символ & в конце указывает оболочке продолжать выполнение службы, пока вы вводите другие команды:
python3 secret_service.py > service.log 2>&1 &
Сохраните идентификатор фонового процесса (PID), чтобы позже корректно его завершить:
echo $! > service.pid
Попробуйте прочитать секрет без токена:
curl -i http://127.0.0.1:8081/secret
Ответ должен содержать 403 Forbidden. Теперь отправьте запрос с необходимым заголовком токена:
curl -s -H "X-Access-Token: lab-token-2026" http://127.0.0.1:8081/secret
Вы должны увидеть:
Project launch code: ORBIT-742
Остановите службу перед переходом к следующему шагу:
kill "$(cat service.pid)"
Запустите проверку для уровня токенов:
python3 service-check.py token
Ожидаемый результат:
token: complete
Обеспечение локальной работы службы
На этом этапе вы подтвердите уровень сетевой защиты. Служба, которой требуется только локальный доступ, должна привязываться к 127.0.0.1 (также известному как localhost). Этот адрес принимает соединения только с того же компьютера.
Проверьте настройку хоста по умолчанию в службе:
grep 'default="127.0.0.1"' secret_service.py
Вы должны увидеть определение аргумента для опции --host. Это значение по умолчанию означает, что при запуске python3 secret_service.py служба начинает работу на localhost.
Снова запустите службу:
python3 secret_service.py > service.log 2>&1 &
Сохраните идентификатор процесса:
echo $! > service.pid
Используйте ss для проверки прослушиваемых TCP-сокетов. Опции -ltn означают прослушивание (listening), TCP и числовые адреса:
ss -ltn | grep ':8081'
Вывод должен показать 127.0.0.1:8081, что подтверждает работу службы только в локальной среде:
LISTEN ... 127.0.0.1:8081 ...
Остановите службу:
kill "$(cat service.pid)"
Запустите проверку для уровня localhost:
python3 service-check.py localhost
Ожидаемый результат:
localhost: complete
Ограничение доступа к секретному файлу
На этом этапе вы добавите уровень прав доступа файловой системы. Даже если в службе есть уязвимость, секретный файл не должен быть доступен для чтения каждой локальной учетной записи.
Проверьте текущие права доступа к файлу:
ls -l secret.txt
Файл изначально имеет более широкие права доступа, чтобы вы могли их ограничить. Используйте chmod 600, чтобы сделать файл доступным для чтения и записи только его владельцу:
chmod 600 secret.txt
Снова проверьте права доступа:
ls -l secret.txt
Теперь биты прав доступа должны начинаться с -rw-------:
-rw------- ... secret.txt
Запустите проверку для этого уровня:
python3 service-check.py permissions
Ожидаемый результат:
permissions: complete
Логирование отклоненных запросов
На этом этапе вы протестируете уровень обнаружения. Блокировка неавторизованного запроса полезна, но запись факта отклонения дает операторам доказательства того, что кто-то пытался получить доступ к защищенному маршруту.
Удалите старый файл логов, чтобы начать этот этап с чистого листа:
rm -f access.log
Запустите службу:
python3 secret_service.py > service.log 2>&1 &
Сохраните идентификатор процесса:
echo $! > service.pid
Отправьте запрос без токена:
curl -s http://127.0.0.1:8081/secret
Тело ответа должно быть:
forbidden
Просмотрите лог доступа:
cat access.log
Лог должен содержать записи rejected, /secret и missing_or_bad_token.
Остановите службу:
kill "$(cat service.pid)"
Запустите проверку для уровня логирования:
python3 service-check.py logging
Ожидаемый результат:
logging: complete
Комплексная проверка уровней защиты
На этом этапе вы проверите итоговый результат эшелонированной защиты. Служба должна требовать токен, по умолчанию оставаться локальной, защищать секретный файл правами доступа только для владельца и логировать отклоненные запросы.
Запустите полную проверку:
python3 service-check.py all
Каждый уровень должен быть пройден:
token: complete
localhost: complete
permissions: complete
logging: complete
Запустите службу в последний раз:
python3 secret_service.py > service.log 2>&1 &
Сохраните идентификатор процесса:
echo $! > service.pid
Убедитесь, что секрет по-прежнему доступен при авторизованном запросе:
curl -s -H "X-Access-Token: lab-token-2026" http://127.0.0.1:8081/secret
Вы должны увидеть:
Project launch code: ORBIT-742
Остановите службу:
kill "$(cat service.pid)"
Эта финальная проверка важна, так как эшелонированная защита должна обеспечивать безопасность службы, не нарушая при этом её штатную работу для авторизованных пользователей.
Резюме
Вы отработали принципы эшелонированной защиты, применив несколько уровней контроля к одной небольшой службе. Вы проверили требование токена, привязку только к локальному интерфейсу, права доступа к файлу только для владельца и логирование отклоненных попыток доступа.
Главный урок заключается в том, что каждый уровень защищает от определенной точки отказа, при этом функциональность службы для авторизованных пользователей остается неизменной.



