Привет, Хабр!

С вами инженерный отдел по динамическому анализу Swordfish Security. Продолжаем разбирать полезные кейсы, и сегодня мы рассмотрим, как в DAST-сканере OWASP ZAP настроить автоматическую авторизацию в приложении и переиспользовать ее в дальнейших сканированиях.

Содержание:

  1. Введение

  2. Создание контекста

  3. Автоматизация с помощью API

  4. Автоматизация с помощью Automation Framework

  5. Вместо вывода

Введение

OWASP ZAP (Zed Attack Proxy) — один из самых популярных инструментов для проверки безопасности веб-приложений. У него широкий диапазон возможностей для обнаружения уязвимостей. Однако, прежде чем начать сканирование, необходимо правильно настроить инструмент, в том числе и авторизацию, чтобы тестировать приложение с одной или нескольких учетных записей.

В DAST-инструментах при настройке сканирований можно встретить различные термины. Авторизация обычно выделяется отдельно и может называться, например, «Профиль авторизации». В ZAP'е есть более широкое понятие для настройки — «Контекст». Это набор информации о приложении, который может быть использован для проведения тестирования. Контекст включает в себя URL-адреса, используемые в продукте, технологиях и параметрах, учетные данные и настройки по поддержанию сессии и прочую информацию, которая может пригодиться при анализе безопасности.

В OWASP ZAP можно создать несколько контекстов, все они будут иметь уникальный набор настроек. Для каждого приложения генерируется отдельный контекст. Также можно создать один набор для основного сайта и другой, например, для административной панели. Контексты позволяют фокусироваться на определенных частях приложения и проводить тестирование только для выбранного набора данных.

Контекст сохраняется в формате XML-файла. Его можно импортировать в GUI-версию инструмента или же использовать для старта автоматизированного сканирования, например в Docker-контейнере. Рассмотрим оба варианта.

Создание контекста

ZAP поддерживает несколько режимов аутентификации: ручной, с помощью формы, HTTP, отправки JSON-данных и с помощью настраиваемого скрипта. Недавно у нас выходила статья про поддержку сессии в OWASP ZAP на основе заголовков. А сейчас давайте разберемся, как настроить контекст с аутентификацией с помощью формы.

Вот вам пошаговый пример на базе формы из GUI ZAP'а:

0. Подключить ZAP как веб-прокси в браузере и открыть сканируемый сайт.
1.1. Поймать в ZAP запрос к первой странице сайта.
1.2. Найти в ZAP аутентификационный запрос (обычно это POST с параметрами username=&password=).
2.1. Добавить сайт из дерева (оно создается ZAP'ом автоматически) в контекст (правый клик на сайт → Include in Context).
2.2. Найти в дереве аутентификационный запрос и сделать правый клик → flag as context → form based authentication.

 Рис. 1. Помечаем запрос как аутентификационный
Рис. 1. Помечаем запрос как аутентификационный

2.3. Найти ответ сервера, а в нем — строку, которая бы говорила о состоянии логина/логаута. Выделить ее и сделать правый клик → Flag as context → login/logout condition. Для заведомо уязвимого приложения WebGoat была выбрана строка «Location: ..../login», так как при попытке открыть страницу в неаутентифицированном состоянии происходит перенаправление на страницу логина.

 Рис. 2. Добавляем индикатор логаута
Рис. 2. Добавляем индикатор логаута

Также можно настроить, чтобы ZAP периодически делал запрос на какую-либо аутентифицированную страницу и проверял ответ — сохраняется сессия или нет.

 Рис. 3. Пример из другого контекста
Рис. 3. Пример из другого контекста

3.1. В настройках контекста (раздел Users) нужно добавить нового пользователя и его пароль. Впоследствии эти данные будут применяться для аутентификации и проверки авторизации.

 Рис. 4. Добавление учетной записи
Рис. 4. Добавление учетной записи

3.2. Чтобы проверить настройки аутентификации, нужно дважды кликнуть на контексте и открыть раздел Authentication. Здесь можно заметить, что пользователь и пароль заданы шаблонами, в которые будут подставляться данные из раздела Users:

 Рис. 5. Автоматическая подстановка имени пользователя и пароля
Рис. 5. Автоматическая подстановка имени пользователя и пароля

Далее стоит заполнить раздел по управлению сессией, выбрав нужный пункт:

 Рис. 6. Управление сессией
Рис. 6. Управление сессией

Рекомендуется начать с автоматического управления сессией (auto-detect). Если этот вариант не сработает, можно настроить поддержку с помощью cookie, заголовка, HTTP-аутентификации или указать скрипт для управления сессией.

Таким образом мы добавили приложение в контекст и настроили аутентификацию и поддержку сессии. Можно заполнить и другие параметры, важные для сканирования, например, указать используемые технологии в соответствующей вкладке.

После настройки контекста можно запускать перебор сайта пауком и активное сканирование прямо в интерфейсе. Но сейчас нас больше всего интересуют возможности автоматизации сканирований с применением подготовленного контекста. И для начала мы экспортируем его:

 Рис. 7. Экспорт контекста
Рис. 7. Экспорт контекста

При экспорте создается файл с расширением context, но, если открыть документ после экспорта, станет понятно, что он составлен в XML-формате. В дальнейшем этот файл может быть импортирован обратно в ZAP, использован для запуска сканирования через API либо передан в качестве параметра в скрипт автоматизации ZAP.

Автоматизация с помощью API

Для работы с API ZAP'а необходимо запустить его в режиме сервиса следующим образом:

$ ./zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true -newsession 20_07-api_session

Данные, собранные в рамках работы с API, будут сохранены в файл сессии, который потом можно переиспользовать.

ВАЖНО: команда, приведенная выше, содержит небезопасные параметры api.disablekey=true и api.addrs.addr.name=.*, которые открывают доступ к API любых хостов без ключа. В неизолированном окружении так делать не стоит!

В дальнейшем можно посылать команды, например, при помощи CURL следующим образом:

Импортируем нужный нам контекст:

curl "http://address:8080/JSON/context/action/importContext/?contextFile=webgoat.context"

Запускаем обход сайта:

scanId=$(curl "http://address:8080/JSON/spider/action/scanAsUser/?contextId=1&userId=643&url=http%3A%2F%2Fapp_address%3A8090%2FWebGoat%2Fwelcome.mvc&maxChildren=&recurse=&subtreeOnly=" | jq '.["scanAsUser"]')

Запускаем активное сканирование:

ascanId=$(curl "http://address:8080/JSON/ascan/action/scanAsUser/?url=http%3A%2F%2Fapp_address%3A8090%2FWebGoat%2Fwelcome.mvc&contextId=1&userId=643&recurse=&scanPolicyName=&method=&postData=" | jq '.["scanAsUser"]')

После завершения тестирования можно создать отдельный файл с уязвимостями конкретного уровня критичности, в данном случае среднего:

curl "http://address/HTML/alert/view/alerts/?baseurl=&start=&count=&riskId=2" > medium.html

А также посмотреть общие результаты анализа:

curl "http://address:8080/JSON/alert/view/alertsSummary/?baseurl="

И, конечно, сгенерировать отчет:

curl "http://address:8080/JSON/reports/action/generate/?title=report&template=traditional-json&theme=&description=&contexts=http%3A%2F%2Fapp_address%3A8090&sites=&sections=&includedConfidences=&includedRisks=&reportFileName=&reportFileNamePattern=&reportDir=&display="

Подобные команды можно собрать в шаг сканирования приложения в том же Gitlab CI/CD, чтобы автоматически получать готовый отчет.

OWASP ZAP предоставляет обширный перечень API ручек, в том числе для детальной настройки сессии. Контекст приложения также может быть сгенерирован через API. Но первичное создание удобнее проводить через интерфейс, к тому же там всё экспортируется файлом, который легко переиспользовать.

Автоматизация с помощью Automation Framework

Второй вариант — применение аддона Automation Framework. Он присутствует в ZAP по умолчанию и позволяет автоматизировать основные задачи, выполняемые инструментом. Для этого в качестве входного параметра для скрипта запуска ZAP zap.sh подключается YAML-файл с конфигурацией нужных задач. Сейчас в документации ZAP’а этот вариант автоматизации указан как предпочтительный.

Вся настройка осуществляется внутри YAML-файла, запуск происходит одной командой:

./zap.sh -cmd -autorun config.yaml

Создать YAML-файл можно либо ключом -autogenmin или -autogenmax к скрипту zap.sh, который идет в дистрибутиве ZAP, либо через UI — в нижней панели добавляется закладка Automation, конфигурируется и далее экспортируется в документ.

 Рис. 8. Automation Framework
Рис. 8. Automation Framework

Этот файл позволяет описать контексты, то есть сканируемые приложения, их настройки аутентификации и пользователей, а также задачи, которые будут выполняться для этих контекстов.

Процесс создания контекста мы рассмотрели выше. При генерации нового плана выбирается уже настроенный контекст, также можно добавить один из профилей задач по умолчанию или создать свой.

 Рис. 9. Создание нового плана
Рис. 9. Создание нового плана

Под задачами понимаются запуски аддонов, позволяющие выполнять различные действия, такие как построение структуры приложения (как простое, так и при помощи AJAX-паука), пассивное и активное сканирование, фильтрация найденных уязвимостей, создание отчетов. Предполагается, что к Automation Framework (который сам является аддоном) можно подключать дополнительные аддоны под разные требования.

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

 Рис. 10. Настройка задачи паука
Рис. 10. Настройка задачи паука

Также для задач можно выставить критерий успешности, например, считать обход сайта удачным, если было найдено более 100 URL.

После настройки запустим Automation Framework. Если сканирование прошло успешно, можно экспортировать YAML-файл настроек и в дальнейшем использовать его для автоматизации. Узнать, насколько успешно прошло сканирование, получится по Output вкладке, в ~/.ZAP/zap.log или на панели AF, где будет частично сообщаться о результатах выполнения задач.

Далее этот файл конфигурации можно импортировать в ZAP либо использовать совместно с основным скриптом запуска ZAP zap.sh для выполнения указанных в файле задач.

Вот как может выглядеть подобный шаг в пайплайне:

Пример .gitlab-ci.yml для запуска AF на основе плана

run-zap:      # создаем задачу
tags:
- docker    # задаем тэг раннера, на котором хотим запустить задачу
  image: owasp/zap2docker-stable   # образ из докерхаба или другого репозитория
  before_script:   # то, что выполнится до основного скрипта
    - mkdir -p /zap/wrk/reports    # создаем папку reports для отчета в пути /zap/wrk (этот путь уже изначально есть в контейнере)
  script:    # основной скрипт
    - zap.sh -cmd -addonupdate    # обновляем аддоны (рекомендуется)     - zap.sh -cmd -autorun $CI_PROJECT_DIR/webgoat_config.yaml   # запускаем ZAP AF на базе плана, который лежит в основном репозитории   after_script:  # команды после основного скрипта
    - cp /zap/wrk/reports/webgoat_CI.pdf .    # копируем отчет из контейнера на раннер
    #- cp /home/zap/.ZAP/zap.log .   # копируем лог, если нужен для выявления проблем
  artifacts:
paths:
      - webgoat_CI.pdf  # указываем, какой отчет нам нужен
      #- zap.log  # указываем лог

Вместо вывода

В результате мы получаем отчет по заданному шаблону либо можем вытащить данные в JSON-формате для их дальнейшей обработки. Есть еще третий вариант — настроить интеграцию OWASP ZAP с платформой-оркестратором AppSec.Hub и получать уже готовые дефекты ;)

Полезные ссылки:

Контексты в OWASP ZAP

OWASP ZAP API

OWASP ZAP Automation Framework

Комментарии (1)


  1. olegtsss
    04.08.2023 12:50

    Спасибо за материал, интересно было почитать. Вот эта история с контекстами и кукой выходит очень костыльной.
    1) Можете прояснить пожалуйста, зачем так сложно сделано? Какой в этом технический смысл, плюсы от описанного алгоритма (здесь я не имею ввиду API, с ним все понятно)?
    2) Как быть с csrf в Zap?