Практическое занятие №9: проект БД и форма входа, этап 2

1. Проблематика: почему визуальной формы недостаточно?

Иллюзия защищенности

Клиентский интерфейс находится под полным контролем пользователя. Любая валидация в браузере или приложении может быть обойдена отправкой прямого HTTP/TCP запроса.

  • Массовый перебор паролей автоматизированными скриптами.
  • SQL-инъекции в поля ввода логина.
  • Утечка структуры БД при развернутых сообщениях об ошибках.

Решение: эшелонированный протокол в СУБД

База данных выступает финальным барьером и контрольным центром безопасности:

  • Проверка хэша с солью исключает компрометацию при утечке дампа.
  • Счетчики неудачных попыток останавливают атаки перебора.
  • Полный аудит всех событий фиксирует любые аномалии.

2. Базовые концепции: AuthN vs AuthZ

Аутентификация (Authentication, AuthN)

Вопрос: «Кто вы?»

Процесс установления и проверки подлинности субъекта на основе предъявленных учетных данных (логин + пароль, биометрия, ключ ЭЦП).

POST /api/auth/login [login, password]

Авторизация (Authorization, AuthZ)

Вопрос: «Что вам разрешено делать?»

Проверка прав аутентифицированного субъекта на выполнение конкретных операций (чтение, модификация, удаление, просмотр логов).

RBAC: Role 'Storekeeper' → Allow Goods_Write

3. Хранение паролей: Соленое хэширование

Никогда не храните пароли открытым текстом или в обратимом шифровании!

Почему не чистый хэш?

Одинаковые пароли дают одинаковые хэши: SHA256("123456") = e10adc3949...

Злоумышленники используют Rainbow Tables (радужные таблицы) для мгновенного обратного поиска паролей миллионов пользователей.

Криптографическая соль (Salt)

Индивидуальная случайная строка (16+ байт), генерируемая CSPRNG для каждого пользователя при регистрации:

hash = SHA256(password || salt)

Даже с одинаковым паролем хэши в базе гарантированно уникальны. Радужные таблицы полностью бессильны!

4. Реляционная схема: атрибуты безопасности учетной записи

Атрибут Тип данных Назначение в механизме защиты
login VARCHAR(50) UNIQUE Идентификатор учетной записи (уникальный индекс для быстрого точечного поиска).
password_hash CHAR(64) SHA-256 хэш строки (password || salt) в шестнадцатеричном виде.
salt CHAR(32) Индивидуальная соль пользователя (16 байт шестнадцатеричной строки).
is_active BOOLEAN Флаг активности аккаунта (деактивация при увольнении или компрометации).
failed_attempts INT DEFAULT 0 Счетчик неудачных попыток ввода пароля подряд.
locked_until TIMESTAMP NULL Временная метка окончания блокировки учетной записи.

5. Алгоритм верификации: Поиск и статус блокировки

Этап 1: Проверка существования и блокировок

  1. Точечный поиск по логину: SELECT * FROM app_users WHERE login = ?;
  2. Если логин не найден: фиксируем AUTH_FAILURE в логе, отдаем клиенту «Неверный логин или пароль» (предотвращение перечисления учетных записей — User Enumeration).
  3. Проверка locked_until: если locked_until > CURRENT_TIMESTAMP → вход невозможен, статус ACCOUNT_LOCKED, сообщаем пользователю время ожидания.
  4. Проверка активности: если is_active = FALSE → статус ACCOUNT_DEACTIVATED, отказ в авторизации.

6. Алгоритм верификации: Вычисление хэша и сравнение

Этап 2: Вычисление и валидация

-- Серверный псевдокод
v_calc_hash := SHA256(input_password || user_record.salt);

IF v_calc_hash = user_record.password_hash THEN
    -- ПАРОЛЬ ВЕРЕН!
    -- Сбрасываем счетчик и снимаем блокировку:
    UPDATE app_users SET failed_attempts = 0, locked_until = NULL WHERE user_id = ...;
    -- Записываем успешный вход в аудит:
    INSERT INTO security_audit_log (event_type, user_id, status) VALUES ('AUTH_SUCCESS', ..., 'SUCCESS');
ELSE
    -- ПАРОЛЬ НЕВЕРЕН! Инкрементируем счетчик неудач...
END IF;

7. Защита от Brute-Force: failed_attempts и locked_until

Механика инкремента

При неверном пароле:

failed_attempts := failed_attempts + 1;

IF failed_attempts >= 3 THEN
  locked_until := NOW() + INTERVAL '15 minute';
  event := 'ACCOUNT_LOCKED';
ELSE
  event := 'AUTH_FAILURE';
END IF;

Почему именно временная блокировка?

  • Остановка ботнетов: скорость перебора падает с 1000 поп/сек до 3 поп / 15 минут.
  • Самовосстановление: легитимный пользователь через 15 минут снова может войти без обращения в техподдержку.
  • Уведомление безопасности: событие ACCOUNT_LOCKED немедленно сигнализирует SOC о попытке атаки.

8. Журнал безопасности: Security Audit Log

Каждое событие аутентификации подлежит обязательной фиксации в неизменяемом логе:

CREATE TABLE security_audit_log (
    log_id BIGSERIAL PRIMARY KEY,
    event_type VARCHAR(30) NOT NULL,      -- AUTH_SUCCESS, AUTH_FAILURE, ACCOUNT_LOCKED
    user_id INT NULL REFERENCES app_users(user_id),
    attempted_login VARCHAR(50) NOT NULL, -- Введенный логин
    ip_address VARCHAR(45) NOT NULL,      -- IPv4 / IPv6 рабочей станции
    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR(20) NOT NULL,          -- SUCCESS, FAILED, BLOCKED
    details TEXT NULL                     -- Диагностический комментарий
);

Внимание: Запись сырых паролей в журнал аудита категорически запрещена!

9. Расследование инцидентов по журналу аудита

Timestamp Event Type Login IP Address Status Аналитический вывод
10:41:02 AUTH_FAILURE admin 192.168.1.105 FAILED Первая ошибка ввода пароля
10:41:08 AUTH_FAILURE admin 192.168.1.105 FAILED Вторая ошибка (интервал 6 сек)
10:41:14 ACCOUNT_LOCKED admin 192.168.1.105 BLOCKED Превышен лимит (3 ошибки) → блокировка на 15 мин
10:41:20 AUTH_FAILURE admin 192.168.1.105 BLOCKED Попытка подбора во время активного тайм-аута отклонена

10. Динамическая настройка интерфейса по роли (RBAC)

Администратор (ADMIN)

  • Панель управления системой
  • Управление аккаунтами и сброс блокировок
  • Просмотр Security Audit Log
  • Экспорт отчетов и бэкапы

Специалист (OPERATOR)

  • Просмотр и редактирование данных предметной области
  • Формирование заказов / документов
  • Системные кнопки скрыты из UI

Клиент / Студент (USER)

  • Личный кабинет (Read-Only)
  • Просмотр личного профиля
  • Ограниченный функционал

11. Дифференцированные практические кейсы

Вариант 1: Складской учет

Проверка учетных данных кладовщика, блокировка аккаунта на 15 минут при 3 неверных вводах, запись в Security_Log.

Вариант 2: Медицинская карта

Аудит доступа врачей к персональным данным пациентов, фиксация IP рабочей станции и времени, проверка is_active = FALSE.

Вариант 3: Банковский терминал

Валидация оператора, проверка срока годности пароля (password_expiry), требование смены при первом входе.

Вариант 4: Образовательная платформа

Ролевая фильтрация интерфейса: перенаправление студента в ЛК, администратора — в панель управления, аудит сессий.

12. Ошибки проектирования: Чего делать нельзя

Критические антипаттерны

  • Сброс счетчика до проверки: обнуление failed_attempts перед вводом пароля уничтожает всю защиту.
  • Разные сообщения об ошибках: «Логин не найден» раскрывает злоумышленнику валидные учетные записи компании.
  • Хранение соли в секрете: соль не является паролем, она уникальна и может храниться рядом с хэшем в открытой колонке.

Архитектурный эталон

  • Нейтральный ответ: «Неверный логин или пароль».
  • Сброс счетчика неудач строго при верном хэше.
  • Фиксация всех неудачных попыток в security_audit_log.
  • Параметризация SQL-запросов для исключения инъекций.

13. Регламент и критерии оценивания

Порядок выполнения работы

  1. Открыть интерактивный рабочий лист zanyatie.html.
  2. Указать свои реальные ФИО и группу в полях ввода.
  3. Переключиться на назначенный преподавателем вариант кейса.
  4. Спроектировать SQL-запросы верификации и аудита.
  5. Заполнить протокол безопасности и контрольные вопросы.
  6. Сохранить результат и экспортировать в PDF.

Критериальная шкала (макс. 4 балла)

  • 2 балла: корректность логики верификации пароля и расчет соленого хэша.
  • 1 балл: реализация счетчика неудач, блокировки и журнала аудита.
  • 1 балл: ролевая адаптация UI и полные ответы на блок самопроверки.

14. Классика веб-безопасности: Little Bobby Tables

Веб-комикс xkcd #327: Exploits of a Mom (Little Bobby Tables)
Тематический интернет-мем: «Exploits of a Mom» (культовый веб-комикс про «Little Bobby Tables», xkcd №327).
Автор: Randall Munroe. Первоисточник: xkcd.com/327. Лицензия: Creative Commons Attribution-NonCommercial 2.5 Generic (CC BY-NC 2.5).
Связь с темой занятия: Мама назвала сына Robert'); DROP TABLE Students; --. Когда школа вставила имя ученика через конкатенацию SQL-строки, база данных стерла всех студентов года. Занятие 26 учит будущих разработчиков: использование параметризованных запросов, строгая верификация паролей и ведение журнала безопасности исключают взлом и потерю критических данных!
1 / 15