D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Автор petrinh1988
Источник https://xss.is
В какой-то момент понял, что трачу время на банальные операции: загружаю таргеты в окуня, запускаю сканирование на SQLi, удачные сканирования перекидываю в мап. Не порядок, тем более у Acunetix 100% должен быть API. В целом, данную заметку можно рассматривать, как знакомство с API Acunetix на полезном примере.
Сразу оговорюсь, что не буду здесь рассматривать сопутствующие части, такие как получение таргета для добавления, создание очереди сканирования в SQLMAP или организация сетевого взаимодействия между элементами цепи. Эти части у всех могут быть организованы по своему. Кто-то базу входящих таргетов сложит в обычный текстовый файл, кто-то в базу sqllite. Тоже касается и сетевых нюансов, окунь и sqlmap могут работать в рамках одной машины, могут быть на разных вирталках или вовсе разных серверах. Поэтому, по максимуму постараюсь оставить все за кадром. На выходе хочу получить рабочий скрипт, который максимально автоматизирует процесс работы.
Схему работы скрипта я придумал такую:
1. Acunetix Version: 24.2.240226074 для Windows отученную от жадности Pwn3rzs
2. Postman
3. VS Code
Исследование API Acunetix
Открываю Acunetix -> Администратор -> Профиль и в самом низу нахожу то, что хотел:
Супер! Ключ есть, документация есть. Из документации узнаем стандартный адрес REST API: https://127.0.0.1:3443/api/v1/ Самое время поиграться в Postman, после накидать нужный скрипт, например, на Python.
Acunetix очень хороший инструмент, но то, как организован в интерфейсе доступ к данным… зачастую логика разработчиков непонятна. Это подсказывало, что работа с API не станет легкой прогулкой. И да, чутье не подвело. Документация API не самая точная. С другой стороны, это некий тест на минимум знаний в пентестинге — сможешь догадаться, как пользоваться API, добро пожаловать. Ну а если нет, то зачем ты вообще установил окуня?
Ссылка на локальную документацию API: https://localhost:3443/Acunetix-API-Documentation.html#-scans именно ей я пользовался и на нее всю дорогу ругался.
Авторизация REST API
Тут все просто. Токен лежит в профиле, а передавать его нужно обычным заголовком X-Auth, без танцев с бубном:
Получаем активные сканирования
Первое, что хотелось бы реализовать — проверку активных сканирований. Документация предлагает нам следующий запрос:
Bash: Скопировать в буфер обмена
Для фильтрации предусмотрены GET-параметры:
c - Cursor indicating which index is the head of the next batch of elements (generally coupled with a limit).
l - Maximum number of items returned. Parameter defaults to 100 if not passed. Limit ranges accepted are less than 100 or greater than 1 (1 < limit < 100).
q - Query to filter results based on a number of filters.
s - none
Черт с ним с “s”, вероятно в других запросах этот параметр и имеет смысл, смотрим чего можно положить в “q”:
Код: Скопировать в буфер обмена
Нас интересует scan_status, но вот первая нестыковка. В примерах справки выше, обращение через “q” выглядит так: ?q=scan_status
rocessing. Здесь же нам предлагается использовать scan_status, как самостоятельный параметр. Окей, попробуем по всякому.
Request: https://127.0.0.1:3443/api/v1/scans?q=scan_status
rocessing
JSON: Скопировать в буфер обмена
Упс… не то. Попытка использовать, как scan_status в виде отдельного параметра, выдает результат без какой либо фильтрации. Не буду томить. Решение подсказала панель управления Acunetix, там параметр выглядит как “status”. Верный URL запроса такой:
https://127.0.0.1:3443/api/v1/scans?q=status:processing
Отлично, теперь мы можем видеть количество сканирований, осталось разобраться с добавлением новых таргетов, созданием сканов и получением уязвимостей.
Добавление нового таргета
Для добавления новой цели есть целых два варианта: одиночное и множественное. Вот, что справка говорит про одиночное добавление:
Bash: Скопировать в буфер обмена
Body:
JSON: Скопировать в буфер обмена
Другой вариант — добавлять таргеты пачкой. В дальнейшем, этот вариант станет предпочтительным, но об этом позже. Множественное добавление производится через ендпоинт add и принимает массив таргетов и групп, к которым их нужно прикрепить:
Bash: Скопировать в буфер обмена
Body:
JSON: Скопировать в буфер обмена
Конечно же, чтобы добавить таргеты к группам, нам потребуется получить группы: https://127.0.0.1:3443/api/v1/target_groups В ответ получим JSON с массивом groups.
Пробую создать новый таргет, но хочу сразу поместить его в группу с идентификатором “633495df-f965-473c-86e8-785eef521a7e”. Учитывая, что документация по API составлена по принципу “лишь бы было”, пытаюсь запихать группу в group_id. Таргет создался, но в группе пусто. Скажу сразу, что через добавление одиночного таргета у меня не получилось создать цель с добавлением в группу. На всякий случай попробовал отследить добавление ручками
Оказалось, что сам окунь добавляет таргет через множественное добавление. Похоже, других способов сразу прицепить группу не существует. А для меня группы важны, я при помощи них группирую… ))) Если серьезно, удобно разбивать по источникам таргетов, чтобы потом можно было проанализировать деятельность. Ну или найти “затерявшийся” таргет.
Мне не принципиально. Буду тогда использовать групповое добавление. Зато, мы увидели, какие параметры реально ждет REST API. Указанные в справке параметры type и criticality, тоже нужны, но мне достаточно их значений по умолчанию.
После создания таргета, вернулся его идентификатор. Он потребуется для запуска, но сначала сделаю шаг назад и поищу запрос, который позволит проверить есть ли url в базе. Логично же, что перед добавлением таргета, нужно проверить нет ли его уже в базе? Как говориться, лучше поздно, чем никогда.
В документации ничего дельного по этому поводу не нашел, поэтому снова смотрю запросы самого Acunetix: https://127.0.0.1:3443/api/v1/targets?q=text_search:*https://pornhub.com
В ответ приходит объект с массивом targets. В коде это превратится в простую проверку количества объектов.
Создаем сканирование через API
Снова смотрю справкус надеждой без надежды, вот описание метода:
Bash: Скопировать в буфер обмена
Body
JSON: Скопировать в буфер обмена
Что-то много всего он просит… и, конечно же, никакой развернутой информации по запросу нет. Давайте по порядку. Сначала разберемся с profile_id. Это ничто иное, как профиль сканирования. Запросить профили сканирования можно через метод API : https://127.0.0.1:3443/api/v1/scanning_profiles
Скорее всего, если у вас установлена нуленная версия, профили сканирования будут как у меня:
Спойлер: Полный JSON-ответ
JSON: Скопировать в буфер обмена
Меня интересует SQL Injection, поэтому использовать буду профиль “11111111-1111-1111-1111-111111111113”
Пробую создать сканирование только с таргетом и профилем сканирования, но нет… нужно все же указывать свойство schedule
Чтобы не тратить время впустую, создаю сканирование через интерфейс и копирую оттуда часть запроса:
JSON: Скопировать в буфер обмена
Тестирую в Postman и получаю параметры вновь созданного сканирования. Проверяю в интерфейсе - все ок, сканирование создано!
Получаем информацию по уязвимостям:
Вторая часть не менее важная - получить данные по уязвимостям и передать их на сканирование в SQLMAP. Пока, соответственно, разбираем нужные нам методы API Acunetix.
Завершающий шаг знакомства с API. Нам нужен этот ендпоинт:
Bash: Скопировать в буфер обмена
Как мы договорились в самом начале, никакой информации по параметрам запроса разработчики не предоставляют. Снова полез смотреть запросы окуня. Запрос с фильтрацией по SQL Injection выглядит так:
https://localhost:3443/api/v1/vulne...2d-1a152945cdae;status:!ignored;status:!fixed;
Если точнее, вот сам фильтр: q=vt_id:db04b846-7dec-fb62-f12d-1a152945cdae;
Факт, что тип уязвимости нужно искать по идентификатору, а не тэгу, меня не очень радует. С одной стороны, боль-мень надежно. С другой стороны, при ручном вводе фильтра выдает еще всякие варианты с “SQL Injection”. В общем, чтобы узнать идентификаторы уязвимостей, можно воспользоваться текстовым поиском по типам уязвимостей:
https://localhost:3443/api/v1/vulnerability_types?q=text_search:*sql injection
Обратите внимание на “*”. Без этого поиска не случится, в ответ вы получите сообщение о неправильном операторе.
Последним штрихом будет получение деталей уязвимости, а именно: сам реквест с пэйлоадом, указанием уязвимого параметра и тип инъекции. Для этого обращаемся к тому же ендпоинту, только добавляем идентификатор уязвимости. Пример: https://127.0.0.1:3443/api/v1/vulnerabilities/3339540470580643701
В целом, это все, что потребуется от API. Хотя, возможно вам захочется реализовать простой механизм фильтрации отработана инъекция sqlmap или не отработана, через статус уязвимости. Тогда потребуется сделать простой PUT-запрос:
Bash: Скопировать в буфер обмена
Body
JSON: Скопировать в буфер обмена
Например: https://localhost:3443/api/v1/vulnerabilities/3352451120738862639/status
Скрипт автоматизации на Python
Код достаточно простой. Конечно же, не претендующий на идеальность/универсальность или какие-то другие варианты. Более того, я в целом не часто использую Python, это хорошо видно по неказистым конструкциям, а так же по абсолютному непониманию, как в Python правильно бросить исключение и правильно его обработать)))) Но похоже в ИБ это самый используемый язык, поэтому решил писать на нем.
В общем, воспринимайте, как просто одну из возможных реализаций с текстовым файлом на входе. Напомню, что я максимально пытался избежать любых сопутствующих тем, но все же решил оставить один из вариантов реализации очереди запуска сканов sqlmap, чтобы скрипт можно было просто Скачать
Источник https://xss.is
В какой-то момент понял, что трачу время на банальные операции: загружаю таргеты в окуня, запускаю сканирование на SQLi, удачные сканирования перекидываю в мап. Не порядок, тем более у Acunetix 100% должен быть API. В целом, данную заметку можно рассматривать, как знакомство с API Acunetix на полезном примере.
Сразу оговорюсь, что не буду здесь рассматривать сопутствующие части, такие как получение таргета для добавления, создание очереди сканирования в SQLMAP или организация сетевого взаимодействия между элементами цепи. Эти части у всех могут быть организованы по своему. Кто-то базу входящих таргетов сложит в обычный текстовый файл, кто-то в базу sqllite. Тоже касается и сетевых нюансов, окунь и sqlmap могут работать в рамках одной машины, могут быть на разных вирталках или вовсе разных серверах. Поэтому, по максимуму постараюсь оставить все за кадром. На выходе хочу получить рабочий скрипт, который максимально автоматизирует процесс работы.
Схему работы скрипта я придумал такую:
- Запуск сканирований в Acunetix
- Смотрим количество активных сканирований
- Если количество меньше 7 (в моем случае это комфортное число), добавляем новын таргетв и стартуем их. Иначе идем к п.2.
- Запускаем сканирование в sqlmap уязвимостей из Acunetix
- Ищем новые зависи с sqli
- Если есть, добавляем уязвимости в очередь, если нет - спим.
1. Acunetix Version: 24.2.240226074 для Windows отученную от жадности Pwn3rzs
2. Postman
3. VS Code
Исследование API Acunetix
Открываю Acunetix -> Администратор -> Профиль и в самом низу нахожу то, что хотел:
Супер! Ключ есть, документация есть. Из документации узнаем стандартный адрес REST API: https://127.0.0.1:3443/api/v1/ Самое время поиграться в Postman, после накидать нужный скрипт, например, на Python.
Acunetix очень хороший инструмент, но то, как организован в интерфейсе доступ к данным… зачастую логика разработчиков непонятна. Это подсказывало, что работа с API не станет легкой прогулкой. И да, чутье не подвело. Документация API не самая точная. С другой стороны, это некий тест на минимум знаний в пентестинге — сможешь догадаться, как пользоваться API, добро пожаловать. Ну а если нет, то зачем ты вообще установил окуня?
Ссылка на локальную документацию API: https://localhost:3443/Acunetix-API-Documentation.html#-scans именно ей я пользовался и на нее всю дорогу ругался.
Авторизация REST API
Тут все просто. Токен лежит в профиле, а передавать его нужно обычным заголовком X-Auth, без танцев с бубном:
Получаем активные сканирования
Первое, что хотелось бы реализовать — проверку активных сканирований. Документация предлагает нам следующий запрос:
Bash: Скопировать в буфер обмена
Код:
curl -X GET https://127.0.0.1:3443/api/v1/scans \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Для фильтрации предусмотрены GET-параметры:
c - Cursor indicating which index is the head of the next batch of elements (generally coupled with a limit).
l - Maximum number of items returned. Parameter defaults to 100 if not passed. Limit ranges accepted are less than 100 or greater than 1 (1 < limit < 100).
q - Query to filter results based on a number of filters.
s - none
Черт с ним с “s”, вероятно в других запросах этот параметр и имеет смысл, смотрим чего можно положить в “q”:
Код: Скопировать в буфер обмена
Код:
target: Specific target to filter for.
threat: Level of severity to filter scans by.
business_criticality: Level of business criticality to filter scans for.
scan_status: Scan state to filter by. Multiple values can be added and are comma-separated (e.g. ?scan_status=completed,queued)
profile_id: Scan type to filter scans by (e.g. Crawl Only).
group_id: Target group to filter scans by.
Нас интересует scan_status, но вот первая нестыковка. В примерах справки выше, обращение через “q” выглядит так: ?q=scan_status
Request: https://127.0.0.1:3443/api/v1/scans?q=scan_status
JSON: Скопировать в буфер обмена
Код:
{
"code": 16,
"message": "Validation errors",
"details": [
{
"q": {
"problems": [
{
"error_message:": "Unknown filter key",
"param_path": "q.scan_status",
"code": "invalid_filter"
}
],
"src": "url"
}
}
]
https://127.0.0.1:3443/api/v1/scans?q=status:processing
Отлично, теперь мы можем видеть количество сканирований, осталось разобраться с добавлением новых таргетов, созданием сканов и получением уязвимостей.
Добавление нового таргета
Для добавления новой цели есть целых два варианта: одиночное и множественное. Вот, что справка говорит про одиночное добавление:
Bash: Скопировать в буфер обмена
Код:
# You can also use wget
curl -X POST https://127.0.0.1:3443/api/v1/targets \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Body:
JSON: Скопировать в буфер обмена
Код:
{
"address": "string",
"description": "",
"type": "default",
"criticality": 30
}
Другой вариант — добавлять таргеты пачкой. В дальнейшем, этот вариант станет предпочтительным, но об этом позже. Множественное добавление производится через ендпоинт add и принимает массив таргетов и групп, к которым их нужно прикрепить:
Bash: Скопировать в буфер обмена
Код:
curl -X POST https://127.0.0.1:3443/api/v1/targets/add \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Body:
JSON: Скопировать в буфер обмена
Код:
{
"targets": [
{
"address": "string",
"description": "",
"type": "default",
"criticality": 30
}
],
"groups": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}
Конечно же, чтобы добавить таргеты к группам, нам потребуется получить группы: https://127.0.0.1:3443/api/v1/target_groups В ответ получим JSON с массивом groups.
Пробую создать новый таргет, но хочу сразу поместить его в группу с идентификатором “633495df-f965-473c-86e8-785eef521a7e”. Учитывая, что документация по API составлена по принципу “лишь бы было”, пытаюсь запихать группу в group_id. Таргет создался, но в группе пусто. Скажу сразу, что через добавление одиночного таргета у меня не получилось создать цель с добавлением в группу. На всякий случай попробовал отследить добавление ручками
Оказалось, что сам окунь добавляет таргет через множественное добавление. Похоже, других способов сразу прицепить группу не существует. А для меня группы важны, я при помощи них группирую… ))) Если серьезно, удобно разбивать по источникам таргетов, чтобы потом можно было проанализировать деятельность. Ну или найти “затерявшийся” таргет.
Мне не принципиально. Буду тогда использовать групповое добавление. Зато, мы увидели, какие параметры реально ждет REST API. Указанные в справке параметры type и criticality, тоже нужны, но мне достаточно их значений по умолчанию.
После создания таргета, вернулся его идентификатор. Он потребуется для запуска, но сначала сделаю шаг назад и поищу запрос, который позволит проверить есть ли url в базе. Логично же, что перед добавлением таргета, нужно проверить нет ли его уже в базе? Как говориться, лучше поздно, чем никогда.
В документации ничего дельного по этому поводу не нашел, поэтому снова смотрю запросы самого Acunetix: https://127.0.0.1:3443/api/v1/targets?q=text_search:*https://pornhub.com
В ответ приходит объект с массивом targets. В коде это превратится в простую проверку количества объектов.
Создаем сканирование через API
Снова смотрю справку
Bash: Скопировать в буфер обмена
Код:
curl -X POST https://127.0.0.1:3443/api/v1/scans \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Body
JSON: Скопировать в буфер обмена
Код:
# Пример из документации АПИ
{
"target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
"profile_id": "bfcb6779-b1f9-41fc-92d7-88f8bc1d12e8",
"report_template_id": "e89ef7db-4101-4c97-b7ab-9249efd2d3cd",
"schedule": {
"disable": true,
"time_sensitive": true,
"history_limit": 10,
"start_date": "string",
"recurrence": "string",
"triggerable": false
},
"max_scan_time": 0,
"incremental": false
}
Что-то много всего он просит… и, конечно же, никакой развернутой информации по запросу нет. Давайте по порядку. Сначала разберемся с profile_id. Это ничто иное, как профиль сканирования. Запросить профили сканирования можно через метод API : https://127.0.0.1:3443/api/v1/scanning_profiles
Скорее всего, если у вас установлена нуленная версия, профили сканирования будут как у меня:
Спойлер: Полный JSON-ответ
JSON: Скопировать в буфер обмена
Код:
{
"scanning_profiles": [
{
"checks": [],
"custom": false,
"name": "Full Scan",
"profile_id": "11111111-1111-1111-1111-111111111111",
"sort_order": 10
},
{
"checks": [],
"custom": false,
"name": "Critical / High Risk",
"profile_id": "11111111-1111-1111-1111-111111111112",
"sort_order": 20
},
{
"checks": [],
"custom": false,
"name": "Critical / High / Medium Risk",
"profile_id": "11111111-1111-1111-1111-111111111119",
"sort_order": 30
},
{
"checks": [],
"custom": false,
"name": "Cross-site Scripting",
"profile_id": "11111111-1111-1111-1111-111111111116",
"sort_order": 40
},
{
"checks": [],
"custom": false,
"name": "SQL Injection",
"profile_id": "11111111-1111-1111-1111-111111111113",
"sort_order": 50
},
{
"checks": [],
"custom": false,
"name": "Weak Passwords",
"profile_id": "11111111-1111-1111-1111-111111111115",
"sort_order": 60
},
{
"checks": [],
"custom": false,
"name": "Crawl Only",
"profile_id": "11111111-1111-1111-1111-111111111117",
"sort_order": 70
},
{
"checks": [],
"custom": false,
"name": "OWASP Top 10",
"profile_id": "11111111-1111-1111-1111-111111111129",
"sort_order": 80
},
{
"checks": [],
"custom": false,
"name": "PCI checks",
"profile_id": "11111111-1111-1111-1111-111111111131",
"sort_order": 81
},
{
"checks": [],
"custom": false,
"name": "Sans Top 25",
"profile_id": "11111111-1111-1111-1111-111111111132",
"sort_order": 82
},
{
"checks": [],
"custom": false,
"name": "Malware Scan",
"profile_id": "11111111-1111-1111-1111-111111111120",
"sort_order": 90
}
]
}
Меня интересует SQL Injection, поэтому использовать буду профиль “11111111-1111-1111-1111-111111111113”
Пробую создать сканирование только с таргетом и профилем сканирования, но нет… нужно все же указывать свойство schedule
Чтобы не тратить время впустую, создаю сканирование через интерфейс и копирую оттуда часть запроса:
JSON: Скопировать в буфер обмена
Код:
{
"target_id": "18d1d575-cb54-47f8-9ca9-124f5345f882",
"profile_id": "11111111-1111-1111-1111-111111111113",
"incremental": false,
"schedule": {
"disable": false,
"start_date": null,
"time_sensitive": false
}
}
Тестирую в Postman и получаю параметры вновь созданного сканирования. Проверяю в интерфейсе - все ок, сканирование создано!
Получаем информацию по уязвимостям:
Вторая часть не менее важная - получить данные по уязвимостям и передать их на сканирование в SQLMAP. Пока, соответственно, разбираем нужные нам методы API Acunetix.
Завершающий шаг знакомства с API. Нам нужен этот ендпоинт:
Bash: Скопировать в буфер обмена
Код:
curl -X GET https://127.0.0.1:3443/api/v1/vulnerabilities \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Как мы договорились в самом начале, никакой информации по параметрам запроса разработчики не предоставляют. Снова полез смотреть запросы окуня. Запрос с фильтрацией по SQL Injection выглядит так:
https://localhost:3443/api/v1/vulne...2d-1a152945cdae;status:!ignored;status:!fixed;
Если точнее, вот сам фильтр: q=vt_id:db04b846-7dec-fb62-f12d-1a152945cdae;
Факт, что тип уязвимости нужно искать по идентификатору, а не тэгу, меня не очень радует. С одной стороны, боль-мень надежно. С другой стороны, при ручном вводе фильтра выдает еще всякие варианты с “SQL Injection”. В общем, чтобы узнать идентификаторы уязвимостей, можно воспользоваться текстовым поиском по типам уязвимостей:
https://localhost:3443/api/v1/vulnerability_types?q=text_search:*sql injection
Обратите внимание на “*”. Без этого поиска не случится, в ответ вы получите сообщение о неправильном операторе.
Последним штрихом будет получение деталей уязвимости, а именно: сам реквест с пэйлоадом, указанием уязвимого параметра и тип инъекции. Для этого обращаемся к тому же ендпоинту, только добавляем идентификатор уязвимости. Пример: https://127.0.0.1:3443/api/v1/vulnerabilities/3339540470580643701
В целом, это все, что потребуется от API. Хотя, возможно вам захочется реализовать простой механизм фильтрации отработана инъекция sqlmap или не отработана, через статус уязвимости. Тогда потребуется сделать простой PUT-запрос:
Bash: Скопировать в буфер обмена
Код:
curl -X PUT https://127.0.0.1:3443/api/v1/vulnerabilities/{vuln_id}/status \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-Auth: API_KEY'
Body
JSON: Скопировать в буфер обмена
Код:
{
"status": "fixed"
}
Например: https://localhost:3443/api/v1/vulnerabilities/3352451120738862639/status
Скрипт автоматизации на Python
Код достаточно простой. Конечно же, не претендующий на идеальность/универсальность или какие-то другие варианты. Более того, я в целом не часто использую Python, это хорошо видно по неказистым конструкциям, а так же по абсолютному непониманию, как в Python правильно бросить исключение и правильно его обработать)))) Но похоже в ИБ это самый используемый язык, поэтому решил писать на нем.
В общем, воспринимайте, как просто одну из возможных реализаций с текстовым файлом на входе. Напомню, что я максимально пытался избежать любых сопутствующих тем, но все же решил оставить один из вариантов реализации очереди запуска сканов sqlmap, чтобы скрипт можно было просто Скачать
View hidden content is available for registered users!