Nuclei Templates Creation – My Experience

Nuclei

Nuclei is Community Powered Vulnerability Scanner. Nuclei is created and maintained by ProjectDiscovery – an open-source software company simplifying security operations for hackers and developers. It is based on simple YAML based DSL. Because it is community powered it is completely open-sourced.

As for me it is a vulnerability scanning framework as it provides fundamental building blocks that you can build upon and create complex and sophisticated checks/assessments and automate them.

By the way ProjectDiscovery have bunch of other awesome tools for security automation, please check it out as you might find something very handy for your own use.

Nuclei Templates

Templates are the main building blocks of your security scanning and assessments automation. All of the community created templates are stored in the nuclei-templates repository. ProjectDiscovery are providing bunch of templates out of the box but the main power and flexibility of Nuclei is in customly crafted templates.

There are 5 types of templates:

  1. HTTP – extensive support for various features related to HTTP protocol. Request method can be GET, POST, PUT, DELETE.
  2. Headless – automation of a browser with simple DSL.
  3. Network Requests – kind of automatable Netcat, allowing to send bytes across the wire and receive them, while providing matching and extracting capabilities on the response.
  4. DNS – fully Customizable DNS requests can be sent by nuclei to nameservers and matching/extracting can be performed on their response.
  5. File – modelling templates that can match/extract on filesystem.

Also there are Operators, Preprocessors, Helper Functions and Worklfows.

Workflows are for automation of complex checks and verification, as they allow to define an execution sequence for templates where they will be run on the defined conditions.

Why to contribute ?

There are a lot of articles out there discussing why people should to contribute to any open source projects:

In nutshell they all can be summarized into following bullet points:

  • Learning
    • reading a lot of source code
    • writing cleaner code
    • better understanding of technology
    • work with the smartest people
  • Recognition
    • your code could be used globally
    • build an outstanding portfolio
    • build professional network
  • Community contribution
    • pay back to the community
    • open source projects are inclusive
    • open source projects are sustainable
    • reduces development costs

Personally for me I am trying/doing it from self improving perspective, to learn something new and strengthen current skills. And as a side effect if someone finds it helpful and can benefit from it – that’s AWESOME!

References:

Choose what to template to create

There are a lot of possibilities and options to create sophisticated and complex template but first of all “you need to walk before you run”.

Today there are ~20 categories of Nuclei templates available:

  • cnvd – Chinese National Vulnerability Database vulnerabilities
  • cves – Common Vulnerabilities and Exposures vulnerabilities
  • default-logins – Default credentials for different platforms and devices
  • dns – DNS related checks and queries
  • exposed-panels – exposed admin panels for devices and platforms
  • exposures – different configuration file exposure
  • file – exposed access id and token files
  • fuzzing – different platforms and services fuzzing
  • headless – browser automation scenarios
  • helpers – collection of helper functions scenarios
  • iot – collection of templates related to IoT devices
  • miscellanious – collection of templates that did not fit into specific category
  • misconfiguration – collection of templates targeted to identify platforms and services misconfigurations
  • network – collection of templates with network requests
  • takeovers – collection of templates with platforms and services takeovers
  • technologies – collection of templates with services and platforms fingerprints gathering
  • token-spray – templates that have static API URL endpoints, can be used to test an API token against many API service endpoints.
  • vulnerabilities – collection of templates with vulnerabilities of different services and platforms
  • workflows – collection of workflows, that define an execution sequence for templates

To start slow I decided to create a default login template as it should be relatively easy.

At the time of writing there are 50+ templates for different platforms and services default logins.

Next step is to identify what service or platform we are going to create template for.

Quick review of already existing templates in the repository led me to thought that it has to be pretty generic system with relatively big user base, so decided to go with GLPI.

GLPI is an acronym in French Gestionnaire Libre de Parc Informatique (or “Free IT Equipment Manager” in English). It is IT System Management (ITSM) software tool that helps plan and manage IT changes in an easy way, solve problems efficiently when they emerge and allow to gain legitimate control over company’s IT budget, and expenses. More details about GLPI can be found here.

Based on the size of the GLPI community and variety of 3rd party add-ons available it should be pretty popular.

But Shodan search shows only 446 total instances of GLPI exposed to outside world.

Anyway, I already set my mind into creating template for GLPI default login and was determined to stick to it.

Algorithm/Approach

Next phase of my journey was the execution.

At first I’ve reviewed GLPI documentation and noted default credentials. There are 4 default user profiles in GLPI:

  1. glpi/glpi admin account,
  2. tech/tech technical account,
  3. normal/normal “normal” account,
  4. post-only/postonly post-only account.

My choice was obvious – admin account.

After that I worked on creating test bed and spinning up a GLPI instance, so I could test my template on an actual system with default credentials.

Reference: GLPI Install wizard

Once that was completed I was ready to identify steps, fields and actions that are involved during the sign in to GLPI.

Initial look at the GLPI Login form lead to realization that Login and Password field names are random. (Oh, Well…)

And during POST request we are submitting this random field name and value.

Request Headers

POST /front/login.php HTTP/1.1
Host: 52.188.113.211
Connection: keep-alive
Content-Length: 179
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://52.188.113.211
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.44
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://52.188.113.211/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: glpi_8ac3914e6055f1dc4d1023c9bbf5ce82=q15pogob26r0b3k8nacm1hn4s4

Form Data

fielda616afe5465f75=glpi&fieldb616afe5465f77=glpi&auth=local&fieldc616afe5465f78=on&submit=Submit&_glpi_csrf_token=eef2c49010b2781fa92314d6380b6ab3583508e076ab635bb5339359ecb206d0

Based on the information mentioned above I decided to go with next approach:

  • GET request – to capture random field names
  • POST request – to pass username and password

Pseudo code

 GET Login Page
 Extract Login field name
 Extract Password field name
 Extract Cookie token value
 POST username and password
 Confirm that login was successful

Template Code

id: glpi-default-credentials
info:
  name: GLPI Default Credentials Check
  author: andysvints
  severity: high
  tags: glpi,default-login
  description: GLPI is an ITSM software tool that helps you plan and manage IT changes. Checking is default super admin account(glpi/glpi) is enabled.
  reference: https://glpi-project.org/

requests:
  - raw:
      - |
        GET / HTTP/1.1
        Host: {{Hostname}}
        Upgrade-Insecure-Requests: 1
        Connection: keep-alive
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        Accept-Encoding: gzip, deflate
        Accept-Language: en-US,en;q=0.9,ru;q=0.8,uk;q=0.7
      - |
        POST /front/login.php HTTP/1.1
        Host: {{Hostname}}
        Connection: keep-alive
        Content-Length: 179
        Cache-Control: max-age=0
        Upgrade-Insecure-Requests: 1
        Origin: {{BaseURL}}
        Content-Type: application/x-www-form-urlencoded
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        Referer: {{BaseURL}}
        Accept-Encoding: gzip, deflate
        Accept-Language: en-US,en;q=0.9,ru;q=0.8,uk;q=0.7
        {{name}}=glpi&{{password}}=glpi&auth=local&submit=Submit&_glpi_csrf_token={{token}}
    cookie-reuse: true
    redirects: true

    extractors:
      - type: regex
        name: token
        part: body
        internal: true
        group: 1
        regex:
          - "hidden\" name=\"_glpi_csrf_token\" value=\"([0-9a-z]+)\""

      - type: regex
        name: name
        part: body
        internal: true
        group: 1
        regex:
          - "type=\"text\" name=\"([0-9a-z]+)\" id=\"login_name\" required=\"required\""

      - type: regex
        name: password
        part: body
        internal: true
        group: 1
        regex:
          - "type=\"password\" name=\"([0-9a-z]+)\" id=\"login_password\" required=\"required\""

    matchers-condition: and
    matchers:
      - type: word
        words:
          - '<title>GLPI - Standard Interface</title>'
      - type: status
        status:
          - 200

More Details

Key Takeaways

While I was working on creation of this template I outlined couple of items that seems pretty important from my point of view.

  1. RTFM

There are a lot of documentation available from Nuclei and community. It is worth to spend couple of minutes to thoughtfully review available documentation and already existing templates. Glancing though existing templates will give you more understanding about the approaches and steps other people are taking and help to make sure that you are not creating template which already exists.

2. Indentation is important!

Also dedicate some time to get yourself used to YAML syntax and indentation rules. Make sure you have a clear understanding how different blocks relate to each other using indentation.

3. QA & Templates Validation

In addition to local syntax validation, I strongly suggest to test the template logic at least in your test lab.

Thanks a lot for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.