Безопасность веб-приложений является важной частью разработки приложений. Как разработчики, я думаю, что мы часто забываем об этом или просто игнорируем это. За свою карьеру я многое узнал о безопасности веб-приложений. Тем не менее, я только недавно узнал и познакомился с быстро растущей индустрией «appsec».
Я обнаружил несоответствие между тем, что продавали консультанты по appsec, и тем, что я разрабатывал. Казалось, что консультанты appsec продавали мне страх, главным образом потому, что я думал, что мои приложения безопасны. Поэтому я поставил перед собой задачу узнать больше о безопасности веб-приложений и тестировании на проникновение, чтобы проверить, действительно ли мои приложения защищены. Эта статья является частью этой миссии, как и предыдущие статьи, которые я написал в этой серии.
- Безопасность веб-приложений на Java — Часть I: Демонстрация входа в Java EE 6
- Безопасность веб-приложений Java — Часть II: демонстрация входа в Spring Security
- Безопасность веб-приложений на Java — часть III: демонстрация входа в Apache Shiro
- Безопасность веб-приложений на Java. Часть IV. Программные API входа
Когда я впервые решил, что хочу поговорить о безопасности Webapp, я знал, что будет интереснее, если я покажу аудитории, как взломать и исправить приложение. Вот почему я написал это в свое первоначальное предложение :
Безопасность веб-приложений: разработка. Проникнуть. Защита. Расслабьтесь.
На этом занятии вы узнаете, как реализовать аутентификацию в ваших веб-приложениях на Java, используя Spring Security, Apache Shiro и хорошую управляемую аутентификацию контейнера Java EE. Вы также узнаете, как защитить свой REST API с помощью OAuth и заблокировать его с помощью SSL.
Изучив, как разработать аутентификацию, я познакомлю вас с OWASP, OWASP Top 10, Руководством по тестированию и Руководством по проверке кода. Далее я расскажу об использовании WebGoat для проверки безопасности вашего приложения и коммерческих инструментов, таких как брандмауэры и ускорители веб-приложений.
В то время я не делал много тестирований веб-приложений . Вы можете сказать это по тому факту, что я упомянул WebGoat как инструмент для пентестинга. Со страницы проекта WebGoat :
WebGoat — это намеренно небезопасное веб-приложение J2EE, поддерживаемое OWASP, предназначенное для обучения урокам безопасности веб-приложений. На каждом уроке пользователи должны демонстрировать свое понимание проблемы безопасности, используя реальную уязвимость в приложении WebGoat. Например, на одном из уроков пользователь должен использовать SQL-инъекцию для кражи поддельных номеров кредитных карт. Приложение представляет собой реалистичную среду обучения, предоставляя пользователям подсказки и код для дальнейшего объяснения урока.
Что я действительно хотел сказать и использовать, так это Zed Attack Proxy , также известный как OWASP ZAP. ZAP — это приложение Java Desktop, которое вы устанавливаете в качестве прокси для своего браузера, а затем используете для поиска уязвимостей в вашем приложении. В этой статье объясняется, как вы можете использовать ZAP для тестирования веб-приложений и устранения их уязвимостей.
Приложение, которое я буду использовать в этой статье, — это приложение Ajax Login, которое я использовал на протяжении всей этой серии. Я думаю, это здорово, что такие проекты, как Damn Vulnerable Web App и WebGoat, существуют, но я хотел протестировать тот, который я считаю безопасным, а не тот, который, как я знаю, не безопасен. В этом конкретном примере я буду тестировать реализацию Spring Security, поскольку именно эту среду я чаще всего использую в своих проектах с открытым исходным кодом.
Zed Attack Proxy Tutorial
- Загрузите и запустите приложение
- Установите и настройте ZAP
- Выполнить сканирование
- Исправить уязвимости
- Резюме
Загрузка и запуск приложения
Для начала загрузите приложение и разверните его на жестком диске. Это приложение является законченной версией приложения Ajax Login, на которое есть ссылки в Java Web Application Security — Часть II: демонстрация входа в Spring Security . Для запуска приложения вам потребуется Java 6 и Maven. Запустите его, используя mvn jetty: run и откройте http: // localhost: 8080 в вашем браузере. Вы увидите, что это простое приложение CRUD для пользователей, и вам нужно авторизоваться, чтобы сделать что-нибудь.
Установка и настройка ZAP Zed Attack Proxy (ZAP) является простой в использовании интегрированный инструмент тестирования на проникновение для поиска уязвимостей в веб — приложениях. Загрузите последнюю версию (я использовал 1.3.0) и установите ее в своей системе. После установки запустите приложение и измените порт прокси на 9000 (Инструменты> Параметры> Локальный прокси). Затем настройте в браузере запросы прокси через порт 9000 и разрешите прокси-запросы локального хоста. Я использовал Firefox 4 («Настройки»> «Дополнительно»> «Сеть»> «Настройки подключения»). Когда вы закончите, ваши настройки прокси должны выглядеть следующим образом:
Другой вариант (вместо удаления localhost) — добавить в файл hosts запись с именем вашего производственного домена. Это то, что я сделал для этой демонстрации.
127.0.0.1 demo.raibledesigns.com
Я также настроил Apache для запросов прокси к Jetty со следующими настройками mod_proxy в моем httpd.conf:
<IfModule mod_proxy.c> ProxyRequests Off ProxyPreserveHost Off <VirtualHost *:80> ProxyPass / http://localhost:8080/ </VirtualHost> <VirtualHost *:443> SSLEngine on SSLProxyEngine on SSLCertificateFile "/etc/apache2/ssl.key/server.crt" SSLCertificateKeyFile "/etc/apache2/ssl.key/server.key" ProxyPass / https://localhost:8443/ </VirtualHost> </IfModule>
Выполните сканирование
Теперь вам нужно предоставить ZAP некоторые данные для работы. Используя Firefox, я перешел на http://demo.raibledesigns.com и немного просмотрел список пользователей, добавил нового и удалил существующего. После этого я заметил несколько флагов в пользовательском интерфейсе ZAP в разделе Сайты. Затем я щелкнул правой кнопкой мыши по каждому сайту (один для http и один для https) и выбрал Attack> Active Scan site. Это можно сделать на вкладке «Активное сканирование» в нижней части ZAP, но при одинаковых URL-адресах возникает ошибка . После этого я получил несколько предупреждений: от высокого (межсайтовый скриптинг) до низкого (автозаполнение пароля). На скриншоте ниже показаны различные проблемы.
Теперь давайте посмотрим, как их исправить.
Исправление уязвимостей
Одна из вещей, не упомянутых при сканировании, но № 1 в Семи конфигурациях безопасности (неправильных) в файлах Java web.xml , — это страницы пользовательских ошибок, не настроенные. Пользовательские страницы ошибок настроены в этом приложении, но error.jsp содержит следующий код:
<% if (exception != null) { %> <% exception.printStackTrace(new java.io.PrintWriter(out)); %> <% } else { %> Please check your log files for further information. <% } %>
Отслеживание стека может быть очень полезным для злоумышленника, поэтому важно начать с удаления приведенного выше кода из src / main / webapp / error.jsp .
Остальные проблемы связаны с XSS, автозаполнением и файлами cookie. Давайте начнем с простых. Исправить автозаполнение достаточно просто; просто изменили HTML в login.jsp и userform.jsp, чтобы autocomplete = «off» было частью тега <form>.
Затем измените файл web.xml, чтобы использовать только http и безопасные файлы cookie. Пока вы это делаете, добавьте время ожидания сеанса и режим отслеживания, как рекомендовано в вышеупомянутой статье о неправильной конфигурации web.xml.
<session-config> <session-timeout>15</session-timeout> <cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config> <tracking-mode>COOKIE</tracking-mode> </session-config>
Затем измените конфигурацию Spring Me «Запомнить меня», чтобы она использовала безопасные файлы cookie. Для этого добавьте use-secure-cookies = «true» к элементу <запомнить-me> в security.xml .
<remember-me user-service-ref="userService" key="e37f4b31-0c45-11dd-bd0b-0800200c9a66" use-secure-cookie="true"/>
К сожалению, Spring Security не поддерживает файлы cookie HttpOnly , но появится в будущем выпуске.
Следующая проблема, которую нужно решить, это отключение просмотра каталогов. Вы можете сделать это, скопировав webdefault.xml Jetty (из JAR org.eclipse.jetty: jetty-webapp) в src / test / resources и изменив его <dirAllowed «<init-param> на false:
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class> <init-param> <param-name>acceptRanges</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>dirAllowed</param-name> <param-value>false</param-value> </init-param> <init-param>
Вам также нужно будет изменить конфигурацию плагина, чтобы он указывал на этот файл, добавив его в раздел <webAppConfig> в pom.xml.
<configuration> <webAppConfig> <contextPath>/</contextPath> <defaultsDescriptor>src/test/resources/webdefault.xml</defaultsDescriptor> </webAppConfig>
Конечно, если вы работаете в рабочей среде, вам нужно настроить это в настройках вашего сервера, а не в файле pom.xml.
Затем я решил исправить проблемы с кешем браузера . У меня были следующие настройки в моем декораторе SiteMesh:
<meta http-equiv="Cache-Control" content="no-store"/> <meta http-equiv="Pragma" content="no-cache"/>
Однако, согласно ZAP, первый метатег должен иметь «no-cache» вместо «no-store», поэтому я изменил его на «no-cache».
После внесения всех этих изменений я создал новый сеанс ZAP и снова запустил активное сканирование на обоих сайтах. Ниже приведены результаты:
Я считаю, что первая проблема (подделка параметров) заключается в том, что я показываю страницу с ошибкой, когда существует дублирующий пользователь. Чтобы это исправить, я изменил UserFormController, чтобы он перехватывал исключение UserExistsException и отправлял пользователя обратно в форму.
try { userManager.saveUser(user); } catch (UserExistsException uex) { result.addError(new ObjectError("user", uex.getMessage())); return "userform"; }
Тем не менее, это, похоже, все еще не заставляет тревогу исчезнуть. Это вероятно потому, что я не фильтрую / не экранирую HTML, когда он впервые представлен. Я считаю, что лучшим решением для этого было бы использовать что-то вроде ESAPI OWASP для фильтрации значений параметров. Однако я не смог найти интеграцию с привязкой данных Spring MVC, поэтому решил не пытаться исправить эту уязвимость.
Наконец, я попытался отключить jsessionid в URL, используя предложения из Stack Overflow . Предыдущий параметр в файле web.xml (<tracking-mode> COOKIE </ tracking-mode>) должен сделать это, но, похоже, он не работает с Jetty 8. Другие проблемы (безопасный кеш браузера страниц, куки HttpOnly и безопасный печенье), я не смог решить. Насколько я могу судить, последние две проблемы вызваны Spring Security.
Резюме
В этой статье я показал вам, как выполнить тестирование веб-приложения с использованием Firefox и ZW Attack Proxy (ZAP) OWASP. Я нашел ZAP хорошим инструментом для выявления уязвимостей, но было бы неплохо, если бы у него была функция «повторного тестирования», чтобы увидеть, исправили ли вы проблему для определенного URL. У него есть функция «повторной отправки», но запуск его, похоже, не снимал оповещения после того, как я их исправил.
Проблемы, которые я не смог решить, в основном касались фреймворков (например, файлов cookie Spring Security и HttpOnly) или серверов (Jetty не использует куки для отслеживания). Я подозреваю, что проблемы с Jetty связаны с тем, что он не поддерживает Servlet 3, а также рекламирует. Я считаю, что это справедливо; Я использую вехой релиз в конце концов. Я попытался сканировать http://demo.raibledesigns.com/ajax-login (который работает на Tomcat 7 в Contegix ) и подтвердил, что jsessionid не существует.
Надеемся, что эта статья помогла вам понять, как определить уязвимости в ваших веб-приложениях. Я верю, что ZAP будет становиться все более популярным, когда разработчики узнают об этом. Если вы чувствуете себя честолюбивым и хотите попытаться решить все проблемы в моем приложении Ajax Login, не стесняйтесь размещать его на GitHub .
Если вы хотите больше поговорить о безопасности Webapp, оставьте комментарий, встречайтесь со мной в
Jazoon позже на этой неделе или давайте поговорим в июле на
Über Conf .
От http://raibledesigns.com/rd/entry/java_web_application_security_part4