Вопрос или проблема
Я хочу узнать, опасно ли как-то хранить идентификатор текущей сессии вошедшего пользователя в исходном коде страницы.
Почему я хотел это сделать?
Я пытаюсь поделиться сессией пользователя между двумя приложениями: одним (основным) на PHP и другим на Node.js. Приложение на Node.js используется только для получения данных в реальном времени, но я просто хочу отправлять актуальные данные вошедшим пользователям в приложении на PHP.
Поскольку идентификаторы сессий хранятся в экземпляре Redis, доступном как для PHP, так и для Node, я могу просто отправить идентификатор сессии с клиента на Node.js (с помощью сообщений через веб-сокеты).
Почему не использовать куки, уже присутствующие в браузере пользователя?
Приложение на Node обслуживается на другом хосте. Поэтому куки не будут доступны.
ДА, существует риск, связанный с включением идентификатора сессии в HTML-код, поскольку это облегчает использование уязвимостей XSS для угонов сессий.
Во-первых, доступ к идентификатору сессии из JavaScript является ПЛОХОЙ ПРАКТИКОЙ; куки должны иметь флаг HTTPONLY, чтобы предотвратить это.
В вашем случае, даже если флаг HTTPONLY установлен, наличие идентификатора сессии в теле страницы облегчает доступ к этому идентификатору при эксплуатации XSS и, таким образом, обходит флаг HTTPONLY.
Пока ваш код не содержит ошибок и не подвержен фиксации сессий или XSS и доступен через HTTPS с безопасными куками, вероятно, это нормально – но это очень трудная задача для достижения и поддержания. Когда что-то сломается, будет действительно сложно обнаружить/протестировать/исправить любые проблемы. Решение, которое вы предлагаете, очень хрупкое.
Лучшим решением для совместного использования сессии между различными стеками приложений является предоставление доступа к ним через один и тот же виртуальный хост – таким образом, не будет необходимости мутить с сообщениями для решения проблемы с куками – существуют очень хорошие и стабильные продукты для этого – многие из которых бесплатные (Varnish, Nginx, Apache Traffic Server).
В качестве альтернативы должно быть возможно воспроизвести архитектуру типа SSO для совместного использования сессии между различными виртуальными хостами.
Вы используете HTTPS для ответов с обоих хостов? Если да, то конкретная опасность отсутствует. Если нет, вы только что увеличили потенциальную возможность угона сессий, которая уже существовала для ваших хостов на PHP и Node независимо (из-за сессионных куков) во всех запросах как для ваших PHP, так и для Node хостов.
Пока вы используете SSL, здесь вы относительно в безопасности. Если вы не используете SSL, и есть чувствительные данные, то вы не в безопасности.
Вам, вероятно, следует попробовать AJAX-запрос из вашего PHP-кода, чтобы обновить клиента с актуальными данными, отправляемыми на ваш общий сервер. Это держит все проблемы отдельно и не создаёт ненужную зависимость вашего PHP-кода от одного источника.
Ответ или решение
Хранение идентификатора текущей сессии пользователя в исходном коде HTML страницы может представлять серьезный риск безопасности, особенно если его обрабатывают в скриптах JavaScript. Рассмотрим подробнее возможные угрозы и меры предосторожности.
Почему это опасно?
-
Уязвимости XSS: Если в вашем приложении присутствуют уязвимости кросс-сайтового скриптинга (XSS), злоумышленник может извлечь идентификатор сессии, если он доступен в HTML-коде. JavaScript может манипулировать DOM и, таким образом, получить доступ к этим данным.
-
Проблемы с безопасностью: Хорошей практикой является установка флага
HTTPOnly
для файлов cookie, что делает их недоступными для JavaScript. Однако, даже с этим флагом, публикация идентификатора сессии в теле страницы позволяет злоумышленнику легче воспользоваться уязвимостями. -
Фиксация сессии: Хранение идентификатора сессии в открытом виде может упростить атаки, при которых злоумышленник может перехватить или угонять сессию пользователя, получая доступ к ее данным.
Альтернативные подходы
Чтобы избежать вышеупомянутых рисков, можно использовать более безопасные методы передачи информации между приложениями:
-
Общий виртуальный хост: Наилучший вариант — разместить оба приложения (PHP и Node.js) на одном виртуальном хосте. Это позволит использовать одни и те же cookie и избежать сложностей с обменом данными.
-
Аутентификация через SSO: Рассмотрите возможность реализации архитектуры единого входа (SSO), которая может безопасно делиться идентификаторами сессий между разными доменами.
-
Использование AJAX: Вместо того чтобы напрямую передавать идентификатор сессии в HTML-коде, используйте AJAX-запросы в вашем PHP-приложении для получения данных от Node.js. Такой подход разграничит обе части системы.
Безопасность соединения
Если вы все-таки решите хранить идентификатор сессии в исходном коде, убедитесь, что все соединения защищены с помощью HTTPS. Это значительно снизит риск перехвата данных, хотя сам по себе этот подход остается рискованным.
Заключение
В добавок к вышесказанному, поддержка кода свободной от уязвимостей XSS и фиксирований сессий является сложной задачей, требующей постоянного внимания. Переход на более безопасные архитектурные подходы стоит рассмотреть как более надёжный способ взаимодействия между приложениями.
Таким образом, хранение идентификатора сессии в исходном коде HTML страницы — это тонкий и рискованный подход, требующий тщательной оценки безопасности и обдуманных решений.