• 🔥 Бесплатный курс от Академии Кодебай: «Анализ защищенности веб-приложений»

    🛡 Научитесь находить и использовать уязвимости веб-приложений.
    🧠 Изучите SQLi, XSS, CSRF, IDOR и другие типовые атаки на практике.
    🧪 Погрузитесь в реальные лаборатории и взломайте свой первый сайт!
    🚀 Подходит новичкам — никаких сложных предварительных знаний не требуется.

    Доступ открыт прямо сейчас Записаться бесплатно

Статья Автоматизация OWASP ZAP, Часть 3, Автоматизация тестирования через API

Приветствую снова всех. Извиняюсь за долгое отсутствие, некоторые данную часть ждали больше всего. К сожалению не смог выпустить все оперативно в силу различных причин (в т.ч. и лени :) )
Итак, для тех, кто не знаком, советую ознакомиться с предыдущими вводными частями:
Автоматизация OWASP ZAP. Часть 1. Вводная часть
Автоматизация OWASP ZAP. Часть 2. Запуск в Docker, доступ к API

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

Определения

Сессия - это сессия в рамках которой происходит работа ZAP. Сессии можно создавать, загружать, сохранять. Сессия стартует по факту вместе с ZAP. Ей можно дать имя, и она будет сохраняться. Если открыть новую сессию с таким же именем как и предыдущая, то сессия пересоздастся.
Контекст - по факту выборка того, на что надо обратить внимание. Т.е. набор URL, того, что надо исключить, набор технологий (базы данных, языки программирования и т.д.). Тут же настройка аутентификации, авторизации, отслеживания сессий(для сканирования под Login пользователем) (это вообще отдельная статья может быть по премудростям аутентификации, если будет интересно, смогу в будущем описать или ответить в личке).
Паук и ajax-паук - ну тут стандартно, первый смотрит в ответах урлы и ходит по ним, с обозначенной глубиной. Второй предназначен для JavaScript, т.е. он запускает браузер и через браузер пытается выдернуть динамически формируемые урлы. (Для пауков как раз и важна авторизация и управление сессиями про которые я описал в контексте).
Активное сканирование - это как раз и есть нужный нам модуль. Тут ZAP береn накопленное все добро из прокси и пауков (из статей выше я писал, что я натравливаю end-to-end регрессионные тесты) и делает сканирование (т.е. вставляет пейлоады в различные параметры, в зависимости от настроек активного сканирования).

Код автоматизации и его структура

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

Давайте рассмотрим структуру репки:
Код:
├── Dockerfile
├── Jenkinsfile
Тут в корне, как я писал ранее, находится Dockerfile (чтобы запускать скрипт из докера). И Jenkinsfile. Последний у нас используется дженкинсом, и описывает джобу которую он выполняет после прохождения end-to-end тестов. Т.е. по факту там написано, что надо скачать уже сбилженный докер из registry(развернут у нас же) и запустить его. Образ оказывается в registry в через Gitlab CI/CD и строится каждый раз когда изменения мержатся в мастер, но это уже лирическое отступление.

Далее перейдем к папке scripts где все и находится.

Код:
.
├── api_scan.py
├── configs
├── defectdojo
├── regression_scan.py
├── scan_core
└── slack
Здесь есть два файла. Это и есть основные скрипты описывающие действия ЗАП и других модулей. Их будем рассматривать выше.
slack - здесь описан класс для интеграции со слэк. Делает базовые вещи (шлет сообщения, отчеты, и может удалять отчеты и файлы) через модуль requests.
defectdojo - тут просто один файл который я взял вот отсюда (репозиторий defectDojo). В файле __init__ создал наследованный класс и определил для него нужные мне методы.
configs - тут хранятся различные переменные/настройки которые используются в скриптах.

scan_core тут основные функции обращений к API ZAP и описаны. Кратко пройдемся по папкам:
Код:
├── api_conf.py
├── colors.py
├── __init__.py
├── jobs
│   ├── __init__.py
│   ├── reports.py
│   ├── scans.py
│   └── spiders.py
├── setup
│   ├── auth.py
│   ├── init_context.py
│   ├── __init__.py
│   ├── init_spider.py
│   ├── policy.py
│   ├── proxy.py
│   └── session.py
└── shared_core.py

api_conf.py - тут конфиги различных АПИ. необходимо открыть и отредактировать своими значениями.
shared_core.py какие то общие функции.
Папка setup - тут находятся различные функции предназначенные для настройки ZAP.
job - тут функции которые выполняют различную работу (запускают пауков, активное сканирование, и строит отчеты и отправляет их. Тут же в reports описана интеграция с redmine).

Описание скрипта

Как упоминалось ранее, в папке scripts находятся 2 файла:
Код:
.
├── api_scan.py
└── regression_scan.py

api_scan.py предназначен для сканирования АПИ приложения. Т.е. он подгружает спецификацию и сканирует её. Тут есть недостаток у ЗАП, что он заполняет данные своими данными, поэтому для лучшего тестирования лучше взять у тестировщиков валидные данные и создать отдельный файл, а также запускать сканирование через zap-api-scan.py (который поставляется с ZAP в докере). Кому интересно, объясню позже, расписывать очень долго. Но для пробы пера, сойдет. Так же как доп. материал, советую ознакомиться со статьей авторов:
Обратите внимание, тут должны быть установлены доп. модули: Replacer и OpenAPI (В докере последнее имеется).

Краткие действия в файле:
1. Выключаются все ранее созданные реплэйсеры (они автоматически вставляют данные в запросы отправляемые ZAP, в моем случае это хедер с токеном авторизации или иные данные которые помешают получить токен авторизации). Создаем контекст и задаем ему настройки.​
2.
Python:
token = requests.post(config.site + "auth", json=config.log_pass).json()[config.token_data][/INDENT]
# Load API from url
print(f'Remove replace rule {config.replacer_name} ==> {zap.replacer.remove_rule(config.replacer_name)}')
print(f'Add replacer rule {config.replacer_name} ==> ' + zap.replacer.add_rule(description=config.replacer_name,
                                                                               enabled=True,
                                                                               matchtype="REQ_HEADER",
                                                                               matchstring="Access-Token",
                                                                               matchregex=False,
                                                                               replacement=token))
Делаю Запрос и получаю токен. Удаляю реплэйсер (если был), и создаю новый с полученным токеном. В моем случае это Header вида Token: dsadasdasdsadsadsa4321dsa
3.
Python:
zap.openapi.import_url(url=config.site + config.spec_path, hostoverride=config.site)
Импортируем описание АПИ. После этого в ZAP должно создастся дерево запросов.​
4. Ниже настраиваем параметры активного сканирования (количество потоков, исключаемые из сканирования параметры и urls).​
5. Старт сканирования. С обработкой ошибок и отправлением уведомлений в SLACK​
6. Последними двумя строками, в случае если сканирование завершилось, создаем html отчет и отправляем его в слак.​

regression_scan.py
Настройки сканирования в данном файле можно задавать флагами. Описание флагов можно получить через опцию --help.
По умолчанию скрипт делает активное сканирование (без паука) и и отсылает результаты в Slack и DefectDojo (менеджер уязвимостей).

Давайте быстренько пробежимся по скрипту:
Python:
if args.new_session:[/INDENT]
[INDENT=2]    set_session.new_session()
Создает новую сессию. Это надо перед тем, как стартовать end-to-end тесты. Данный флаг не надо использовать с другими флагами. У нас это запускается Jenkins в prejob (на самом деле создаем новую сессию через curl).​
Python:
    context_id = context_init.set_contex_properties(contextname=conf.contextName,
                                                    include_url=conf.contextIncludeURL,
                                                    exclude_url=conf.contextExcludeURL,
                                                    technology=conf.contextTechnology)
    # Remove "Default context" for exclude all scans not in scope.
    context_init.remove_default_context()
    policy_name = import_scan_policy(policy_name=conf.ImportedPolicyName)
    print(f"{policy_name} was applied for ascan")
Создаем контекст с определенным листом технологий, и исключающими УРЛс. Удаляем дефолтный контекст (чтобы не интересующие нас сайты случайно не залетели в отчет).​
Т.к. у меня тонкая настройка политики, то я ранее создал её в интерфейсе ZAP и положил в папку, которой делаю volume в Docker с ZAP. Тут я её подгружаю. Так же имеются методы, которые позволяют создать политику с собственным именем и выставить для всех пейлоадов определенные одинаковые параметры. (Все значения параметров определяются в конфигах в папке configs).​
Далее не буду копировать код, но если указано, что надо запустить паука, то запускается паук и после его отработки аналогично скрипту и его описанию выше, настраиваются параметры активного сканирования.​
Python:
 # Start Ascan
    try:
        print(f"Start ASCAN with Context {conf.contextName} and policy {policy_name}")
        scans.start_ascan(context_name=conf.contextName, scan_policy=policy_name)
    except ValueError:
        print("Scan_id does not exist. Proxy is empty.")
        slack.post_message_to_slack("ERROR! Proxy is empty!")
        sys.exit()
    except Exception as e:
        print("Error:", e)
        slack.post_message_to_slack("Error: " + str(e))
        sys.exit()
Тут стартует активное сканирование, и обрабатываются ошибки с их отправкой в Slack.​
В следующем модуле генерируются и отправляются отчеты:​
Python:
slack.upload_file(file=html_report)
отправляем файл с отчетом в Slack.​
Python:
add_redmine_issue_notes(type_of_scan='Regression')
отправляем отчет в редмайн (предварительно создал отдельный проект)​
Python:
xml_report = report_gen(type_file='xml')
        dd = DefectDojoTB(product_name=r_conf.dd_name_of_product, engagement_name=r_conf.dd_name_of_engagement)

        print('Upload report to DefectDojo:', dd.import_tb_scan(scan_type=r_conf.dd_scan_type,
                                                                file=xml_report,
                                                                scan_date=datetime.datetime.now().strftime('%Y-%m-%d'),
                                                                tags=r_conf.dd_scan_tag))
Создаем объект класса DefectDojo и далее загружаем xml отчет в заранее созданный product и engagement.​

Заключительное слово
Благодарю всех, кто осилил. По хорошему все это добро надо разбивать на несколько частей. + У ЗАП много еще потайных мест и вещей которые не сразу понятны. К сожалению, я не имею возможности/времени ими поделиться, если будет много вопросов возможно и составлю по ним описания. Зависит от активности и интереса комьюнити.
Так же возможно не все работает, т.к. мною не все функции были протестированы, особенно темное пятно в Пауке(т.к. у меня нет в нем необходимости на настоящий момент). А также не до конца понятен алгоритм Аякс паука. Точнее какой url ему скармливать, в моих приложениях он не очень активно что-то находит.

Так же у ЗАП есть механизмы внутреннего скриптования. Про них можно много рассказывать тоже, и некоторые вещи без скриптов в самом ZAP в современных приложениях к сожалению не реализуемы. Данной области я касался лишь слегка, но большинство вещей все-таки можно выполнить стандартными возможностями OWASP ZAP.​
 
Последнее редактирование:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы