Существует множество статей о том, как настроить аутентификацию и авторизацию в дескрипторе развертывания web.xml. Вместо того, чтобы еще раз рассказывать о том, как настраивать роли, защищать web-ресурсы и устанавливать различные типы аутентификации, давайте рассмотрим некоторые распространенные ошибки в настройках безопасности в файле web.xml.
Эта статья является переводом статьи Seven Security (Mis)Configurations in Java web.xml Files.
-
Не настроены страницы ошибок
По умолчанию web-приложения на Java отправляют подробные сообщения об ошибках прямо в браузер. В этих сообщениях фигурируют версии серверов, трассировка стека, в некоторых случаях в стэк-трэйсах запечатлеваются куски Java-кода. Эта информация является настоящей находкой для хакеров, которые собирают информацию о потенциальной жертве.
К счастью, настроить web.xml так, чтобы вместо стандартных страниц со стек-трейсом выводились указанные пользователем страницы, очень легко. Если использовать приведенную ниже конфигурацию, то при возникновении ошибки с кодом 500, будет показана “хорошая” страница. Таким же образом можно настроить отображение страниц ошибок для других кодов состояний HTTP (например, 404).
<error-page> <error-code>500</error-code> <location>/path/to/error.jsp</location> </error-page>
Кроме того, в web.xml необходимо запретить выдачу страниц со стек-трейсом, с помощью тега exception-type. Вместо этой страницы должна отображаться указанная пользователем. Как видно из примера, мы указываем тип исключения Throwable. Throwable – это базовый класс для всех исключений и ошибок в Java, поэтому такая настройка гарантирует нам, что ни один стек трей не отправится пользователю.
<error-page> <exception-type>java.lang.Throwable</exception-type> <location>/path/to/error.jsp</location> </error-page>
Однако, ваш код может отобразить стек-трейс если вы написали что-то вроде этого:
<% try { String s = null; s.length(); } catch (Exception e) { // don't do this! e.printStackTrace(new PrintWriter(out)); } %>
Не забывайте использовать “правильное” логгирование в дополнение к правильной настройке дескриптора развертывания web.xml.
-
Обход аутентификации и авторизации
Следующий код показывает как установить web-based контроль доступа так, чтобы все, что находится в каталоге secure было доступно только для пользователей с ролью admin.
<security-constraint> <web-resource-collection> <web-resource-name>secure</web-resource-name> <url-pattern>/secure/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint>
Обычно считается, что если есть такая конфигурация, разрешены только GET и POST запросы, однако, это не так. По умолчанию, любой метод является допустимым и приведенная выше конфигурация не ограничивает обращение к ресурсам с помощью методов, отличных от GET и POST. В данной конфигурации говорится лишь что если обращение к ресурсу выполняется с помощью GET или POST, необходимо чтобы пользователь был авторизован. Arshan Dabirsiaghi в своей статье описывает эту проблему и приводит примеры того, как используя HTTP-метод HEAD или даже полностью поддельные методы TEST или JUNK, которые не перечислены в конфигурации web.xml, обойти аутентификацию и авторизацию.
К счастью, решение этой проблемы очень простое. Просто удалите все элементы http-method из web.xml, тогда настройки будут должным образом применены ко всем запросам.
-
Не настроен SSL
SSL должен использоваться везде, где осуществляется передача конфиденциальных данных. Конечно, вы можете настроить SSL на веб-сервере и успокоиться на этом, но вы также можете настроить SSL на уровне веб-приложения как только соответствующие SSL-ключи будут установлены на сервере приложений. Это очень просто.
<security-constraint> ... <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
-
Отказ от использования флага secure
Множество сайтов используют SSL для аутентификации, а затем переходят в не-SSL режим и все общение с сайтом происходит по незащищенному протоколу. Это делает сессионные куки (такие как JSESSIONID) уязвимыми для атаки “захват сессии” (session hijacking). Чтобы этого избежать, куки можно создавать с флагом secure, который гарантирует, что браузер не будет передавать указанные куки по не-SSL протоколу. Выставляется этот флаг таким образом:
<session-config> <cookie-config> <secure>true</secure> </cookie-config> </session-config>
-
Отказ от использования флага HttpOnly
Куки могут быть созданы с флагом HttpOnly, который гарантирует, что они не могут быть доступны клиентским скриптам. Это позволяет защититься от некоторых из самых распространенных XSS атак. Выставляется этот флаг таким образом:
<session-config> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config>
В версиях Tomcat 5.5 и 6.x флаг HttpOnly позволял устанавливать атрибут useHttpOnly для определенного приложения. Этот атрибут находится в элементе Context в файле server.xml. По умолчанию этот атрибут был отключен в версиях Tomcat 5.5 и 6.x, однако в Tomcat 7 атрибут useHttpOnly по умолчанию имеет значение true. Таким образом, в Tomcat 7, даже если в web.xml вы выставите флаг
<http-only>false</http-only>
ваш JSESSIONID по-прежнему будет HttpOnly, если не изменить это поведение в файле server.xml.
-
Использование URL-параметров для отслеживания сессии
Элемент tracking-mode в спецификации Servlet 3.0 позволяет указать, будет JSESSIONID храниться в куках или же будет передаваться как URL-параметр. Если идентификатор сессии хранится в URL-параметре, то он может быть сохранен в истории браузера, на прокси-сервере, в логах и т.д. это делает наше приложение более уязвимым к атаке “захват сессии”. Вместо этого, спецификация Servlet 3.0 предлагает нам хранить JSESSIONID в кукисах. Делается это с помощью следующей конфигурации:
<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>
-
Не настроен таймаут для сессии
Пользователи любят долго живущие сессии потому что они удобны. Хакеры любят долго живущие сессии потому что они дают им больше времени для проведения атак, таких как “захват сессии” или Cross Site Request Forgery. Что выбрать – удобство или безопасность – решать вам, но когда вы определитесь с временем жизни сессии, то можете настроить его следующим образом:
<session-config> <session-timeout>15</session-timeout> </session-config>
В этом примере сессия будет жить в течение 15 минут бездействия пользователя. Если session-timeout не настроен, то спецификация Servlet требует, чтобы использовался таймаут, выбранный поставщиком контейнера (для Tomcat это 30 минут). Если в качестве длины жизни сессии указать отрицательное число или 0, то сессия будет жить “вечно”. Такой подход не рекомендуется применять.
Время простоя также может быть настроено с помощью метода setMaxInactiveInterval класса HttpSession. В отличие от элемента session-timeout, этот метод принимает значение времени в секундах.
Вывод
Создание и развертывание безопасных приложений требует рассмотрения системы с многих сторон. Настройки среды выполнения также важны как и настройки самого web-приложения. Если вы хотите поделиться своими приемами настройки безопасности web-приложений на Java, добро пожаловать в комментарии.


#1 by Slava Semushin on 20 Август 2010 - 21:17
Quote
Я думаю, что если вы перевели статью на русский (за что вам, конечно же, спасибо), то хорошим тоном было бы указать и ссылку на оригинал — https://blogs.sans.org/appsecstreetfighter/2010/08/11/security-misconfigurations-java-webxml-files/
#2 by Дмитрий Леонтьев on 21 Август 2010 - 13:33
Quote
Здравствуйте, Slava! Спасибо за напоминание, ссылку добавил.
#3 by Armen on 2 Декабрь 2010 - 11:28
Quote
Blog ochen xaroshi
#4 by Ярослав on 17 Февраль 2012 - 18:59
Quote
Отличная статья!
У меня вопрос по первой настройке.
Можно ли настроить страницы ошибок сразу для всех кодов или нужно перечислять каждую? Например, одну страницу для 50х.
#5 by Дмитрий Леонтьев on 10 Март 2012 - 12:57
Quote
Здравствуйте, Ярослав!
Если вы используете Servlet 3.0, то можно сделать так:
Таким образом задается общая страница для всех ошибок, даже тех, которые не вызваны исключением, например, 404, 401.
#6 by Дмитрий Леонтьев on 10 Март 2012 - 13:04
Quote
Чтобы настроить одну страницу для 50х ошибок, можно сделать так, как описано в первом пункте статьи:
500 ошибки являются следствием исключений на сервере (Internal Server Error).
#7 by Михаил Зайцев on 27 Март 2012 - 23:48
Quote
Спасибо, Дмитрий. Хорошая статья.
А если я не использую 3-ю версию, есть ли способ не перечислять все коды?