Статьи

Безопасность веб-приложений на Java. Часть V. Проникновение с помощью Zed Attack Proxy

Безопасность веб-приложений является важной частью разработки приложений. Как разработчики, я думаю, что мы часто забываем об этом или просто игнорируем это. За свою карьеру я многое узнал о безопасности веб-приложений. Тем не менее, я только недавно узнал и познакомился с быстро растущей индустрией «appsec».

Я обнаружил несоответствие между тем, что продавали консультанты по appsec, и тем, что я разрабатывал. Казалось, что консультанты appsec продавали мне страх, главным образом потому, что я думал, что мои приложения безопасны. Поэтому я поставил перед собой задачу узнать больше о безопасности веб-приложений и тестировании на проникновение, чтобы проверить, действительно ли мои приложения защищены. Эта статья является частью этой миссии, как и предыдущие статьи, которые я написал в этой серии.

Когда я впервые решил, что хочу поговорить о безопасности 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

Загрузка и запуск приложения
Для начала загрузите приложение и разверните его на жестком диске. Это приложение является законченной версией приложения 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 («Настройки»> «Дополнительно»> «Сеть»> «Настройки подключения»). Когда вы закончите, ваши настройки прокси должны выглядеть следующим образом:

Настройки Firefox Proxy

Другой вариант (вместо удаления 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-адресах возникает ошибка . После этого я получил несколько предупреждений: от высокого (межсайтовый скриптинг) до низкого (автозаполнение пароля). На скриншоте ниже показаны различные проблемы.

ZAP Alerts

Теперь давайте посмотрим, как их исправить.

Исправление уязвимостей
Одна из вещей, не упомянутых при сканировании, но № 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