Nucleoi POC template writing notes

Basic introduction

id

The ID must not contain spaces. This is done to make output parsing easier.

id: git-config

information

The next important information about the template is the information block. The information block provides name, author, severity, description, reference, and label. It also contains a severity field indicating the severity of the template. The information block also supports dynamic fields. Therefore, N key: value blocks can be defined to provide more useful information about the template. Reference is another popular label used to define external reference links for templates.

Another useful tag that is always added to the info block is tags. This allows you to set some custom tags as templates, depending on the purpose and other CVEs. rce this allows the core to identify templates using your input tags and run them only.

info:
  name: Git Config File Detection Template
  author: Ice3man
  severity: medium
  description: Searches for the pattern /.git/config on passed URLs.
  reference: https://www.acunetix.com/vulnerabilities/web/git-repository-found/
  tags: git,config

The actual request and the corresponding matcher are placed under the information block, and they perform the task of sending a request to the target server and finding out whether the template request is successful.

Basic request

request

Nucleoi provides extensive support for various functions related to the HTTP protocol. Supports HTTP requests based on the original and model, as well as non RFC client request options. You can also specify the payload, and you can convert the original request based on the payload value and more functions shown later on this page.

The HTTP request starts with a request block that specifies the start of the template request.

requests:

Request method:

According to the needs of poc, the request methods are GET, POST, PUT, DELETE, etc.

yamethod: GET

redirect

Redirection is not supported by default. If necessary, you can add redirects: true to enable in the request details. Then use the max redirects field. The following number is the number of redirects allowed. By default, up to 10 redirects are followed.

requests:
  - method: GET
    path:
      - "{{BaseURL}}/login.php"
    redirects: true
    max-redirects: 3

route

The next part of the request is the path of the request. Dynamic variables can be placed in paths to modify their behavior at runtime. Variables start with {{and}} and are case sensitive.

{{BaseURL}} - This will replace the input specified in the target file at the run time of the request URL. 

{{RootURL}} - This will request the root in at run time URL Replace with the root specified in the target file URL. 

{{Hostname}} - The hostname variable is replaced with the hostname, including the port of the runtime target.

{{Host}} - This will replace the request for the input host specified in the target file at runtime.

{{Port}} - This replaces the runtime in the request with the input port specified in the target file.

{{Path}} - This replaces the runtime in the request with the input path specified in the target file.

{{File}} - This replaces the runtime in the request with the input file name specified in the target file.

{{Scheme}} - This will replace the request in the template at runtime with the protocol specified in the target file.
VariableValue
{{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
path: "{{BaseURL}}/.git/config"
# This path will be replaced on execution with BaseURL
# If BaseURL is set to  https://abc.com then the
# path will get replaced to the following: https://abc.com/.git/config

Request header

Specifies the request header.

# headers contain the headers for the request
headers:
  # Custom user-agent header
  User-Agent: Some-Random-User-Agent
  # Custom request origin
  Origin: https://google.com

body

The content to be sent when requesting.

# Body is a string sent along with the request
body: "{\"some random JSON\"}"

# Body is a string sent along with the request
body: "admin=test"

Session

When multiple requests are initiated, the session needs to be maintained. You can add cookie reuse: true to maintain the session when multiple requests are made. This is very useful when there is authentication.

# cookie-reuse accepts boolean input and false as default
cookie-reuse: true

Request condition:

The request condition allows the conditions between multiple requests to be checked to write complex checks and exploits involving multiple HTTP requests to complete the exploit chain.

Using the DSL matcher, you can use the corresponding attribute, status, by adding req condition: true and a number as a suffix_ code_ 1 for example. status_ code_ 3 body_ two

    req-condition: true
    matchers:
      - type: dsl
        dsl:
          - "status_code_1 == 404 && status_code_2 == 200 && contains((body_2), 'secret_string')"

Final HTTP request

id: git-config

info:
  name: Git Config File
  author: Ice3man
  severity: medium
  description: Searches for the pattern /.git/config on passed URLs.

requests:
  - method: GET
    path:
      - "{{BaseURL}}/.git/config"
    matchers:
      - type: word
        words:
          - "[core]"

Original HTTP request

Another way to create a request is to use the original request, which has greater flexibility and support for DSL auxiliary functions. For example, the following requests (it is now recommended to keep the Host header as the variable {Hostname} in the example), all matchers and extractors can be used with RAW requests in the same manner as described above.

requests:
  - raw:
    - |
        POST /path2/ HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        a=test&b=pd

You can modify the request as needed. The nucleoi request is fully configurable, which means that you can configure and define each attribute about the request that will be sent to the target server.

The RAW request format also supports: Various auxiliary functions Yes, it allows us to use input for runtime operation, which can save a lot of work.

    raw:
      - |
        GET /manager/html HTTP/1.1
        Host: {{Hostname}}
        Authorization: Basic {{base64('username:password')}} # Helper function to encode input at run time.

HTTP obfuscation test

The nucleoi engine supports the fuzzing module, which allows various types of payloads to be run in various formats. You can use simple keywords to define placeholders (or use {{helper_function(variable)}} to use parentheses when mutation functions are required), and execute the attacks of batteringram, pitchfork and clusterbomb. The thesaurus of these attacks needs to be defined in the Payload field during the request definition. The name matches the keyword. Nucleoi supports thesaurus references based on files and templates. Finally, all DSL functions are fully available and supported, and the final value can be manipulated.

Payloads are defined using variable names and can be referenced between §§ or {}}.

When using a local Dictionary:

    # HTTP Intruder fuzzing using local wordlist.

    payloads:
      paths: params.txt
      header: local.txt

When using lists:

    # HTTP Intruder fuzzing using in template wordlist.

    payloads:
      password:
        - admin
        - guest
        - password

Note: be careful when selecting the attack type, because incorrect input may cause exceptions.

For example, if clusterbob pitchfork is used as the attack type and only one variable is defined in the payload section, the template will not compile because clusterbob or pitchfork expects to use multiple variables in the template.

Attack mode

The nucleoi engine supports a variety of attack types, including the default type of batteringram, which is usually used for a single parameter of fuzzy, and clusterbob and pitchfork are used for multiple parameters of fuzzy. Their working mode is the same as that of the classic burp intruder.

Typebatteringrampitchforkclusterbomb
Support

batteringram

The batteringram places the same Payload in all positions. It uses only one Payload. It traverses the Payload tag bit and replaces all positions with the Payload set traversal.

pitchfork

pitchfork uses one Payload set per location. It places the first Payload in the first position, the second Payload in the second position, and so on.

It then traverses all Payload tag bits at the same time. The first request uses the first Payload in each Payload set, the second request uses the second Payload in each Payload set, and so on.

clusterbomb

The clusterbomb attack attempts all different Payload combinations. It still places the first Payload in the first position and the second Payload in the second position. But when it traverses the Payload set, it tries all combinations.

Then it traverses all the Payload sets at the same time. The first request uses the first Payload in each Payload set, the second request uses the second Payload in each Payload set, and so on.

This type of attack is useful for brute force attacks. Load the common user name list in the first payload set, and load the common password list in the second payload set. Cluster bomb attacks will then attempt all combinations.

clusterbomb is an example of fuzzy testing using attacks.

requests:
  - raw:
      - |
        POST /?file={{path}} HTTP/1.1
        User-Agent: {{header}}
        Host: {{Hostname}}

    payloads:
      path: helpers/wordlists/prams.txt
      header: helpers/wordlists/header.txt
    attack: clusterbomb # Defining HTTP fuzz attack type

Unsafe HTTP request

Nucleoi support rawhttp To achieve complete request control and customization, and allow any type of malformed requests against HTTP request smuggling, host header injection, CRLF with malformed characters, etc.

The rawhttp library is disabled by default and can be enabled by including unsafe: true in the request block.

requests:
  - raw:
    - |+
        POST / HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        Content-Length: 150
        Transfer-Encoding: chunked

        0

        GET /post?postId=5 HTTP/1.1
        User-Agent: a"/><script>alert(1)</script>
        Content-Type: application/x-www-form-urlencoded
        Content-Length: 5

        x=1
    - |+
        GET /post?postId=5 HTTP/1.1
        Host: {{Hostname}}

    unsafe: true # Enables rawhttp client
    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "<script>alert(1)</script>")'

Advanced fuzzy test

Nucleoi allows advanced fuzzy testing of Web servers. You can use several options to tune the HTTP fuzzing workflow.

Assembly line

Added HTTP Pipelining support, allowing multiple HTTP requests to be sent on the same connection.

Before running the template based on HTTP pipeline, please ensure that the running target supports HTTP pipeline connection, otherwise the core engine will fall back to the standard HTTP request engine.

If you want to confirm that the given domain or sub domain list supports HTTP Pipelining, httpx has a flag - pipeline to do so.

Configure an example of displaying pipeline properties of nucleoi.

    unsafe: true
    pipeline: true
    pipeline-concurrent-connections: 40
    pipeline-requests-per-connection: 25000

A sample template demonstrating the function of nucile pipeline

id: pipeline-testing
info:
  name: pipeline testing
  author: pdteam
  severity: info

requests:
  - raw:
      - |+
        GET /{{path}} HTTP/1.1
        Host: {{Hostname}}
        Referer: {{BaseURL}}

    attack: batteringram
    payloads:
      path: path_wordlist.txt

    unsafe: true
    pipeline: true
    pipeline-concurrent-connections: 40
    pipeline-requests-per-connection: 25000

    matchers:
      - type: status
        part: header
        status:
          - 200

Connection pool

Although earlier versions of nucleoi did not have connection pooling, users can now configure templates to use or not use HTTP connection pooling. This allows faster scanning as needed.

To enable connection pooling in the template, threads can define properties using the corresponding number of threads to be used in the payload section.

Connection: the close header cannot be used in the HTTP connection pool template, otherwise the engine will fail and fall back to the standard HTTP request with the pool.

id: fuzzing-example
info:
  name: Connection pooling example
  author: pdteam
  severity: info

requests:

  - raw:
      - |
        GET /protected HTTP/1.1
        Host: {{Hostname}}
        Authorization: Basic {{base64('admin:§password§')}}

    attack: batteringram
    payloads:
      password: password.txt
    threads: 40

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200

      - type: word
        words:
          - "Unique string"
        part: body

smuggle

The most basic example of HTTP sniffing vulnerability is cl.te sniffing. An example for detecting CE Sample template for TL HTTP Smuggling vulnerability, which uses unsafe: true attributes of raw http based requests.

id: CL.TE-http-smuggling

info:
  name: HTTP request smuggling, basic CL.TE vulnerability
  author: pdteam
  severity: info
  lab: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te

requests:
  - raw:
    - |+
      POST / HTTP/1.1
      Host: {{Hostname}}
      Connection: keep-alive
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 6
      Transfer-Encoding: chunked

      0

      G  
    - |+
      POST / HTTP/1.1
      Host: {{Hostname}}
      Connection: keep-alive
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 6
      Transfer-Encoding: chunked

      0

      G

    unsafe: true
    matchers:
      - type: word
        words:
          - 'Unrecognized method GPOST'

Conditional competition

Competitive conditions are another type of error that is not easily automated by traditional tools. Burp Suite introduces a Gate mechanism for Turbo Intruder, in which all bytes of all requests are sent, and the last byte is expected to be sent at the same time. Only all requests for synchronous sending events are sent together.

We implemented the Gate mechanism in the nucleoi engine and allowed them to run through the template, which made the testing of this specific bug class simple and portable.

To enable race condition checking in the template, race can set the attribute to true and race_count defines the number of simultaneous requests to start.

The following is an example template in which requests with the same logic are used 10 times.

id: race-condition-testing

info:
  name: Race condition testing
  author: pdteam
  severity: info

requests:
  - raw:
      - |
        POST /coupons HTTP/1.1
        Host: {{Hostname}}

        promo_code=20OFF    

    race: true
    race_count: 10

    matchers:
      - type: status
        part: header
        status:
          - 200

nuclei -t race.yaml -target https://api.target.com

Multi request contention condition test

For scenarios where multiple requests need to be sent to take advantage of race conditions, we can use threads.

The following is an example template where multiple (5) requests will be sent simultaneously using.

    threads: 5
    race: true

threads is the total number of requests issued using the template to perform race condition tests.

id: multi-request-race

info:
  name: Race condition testing with multiple requests
  author: pd-team
  severity: info

requests:
  - raw:  
      - |
        POST / HTTP/1.1
        Pragma: no-cache
        Host: {{Hostname}}
        Cache-Control: no-cache, no-transform
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

        id=1

      - |
        POST / HTTP/1.1
        Pragma: no-cache
        Host: {{Hostname}}
        Cache-Control: no-cache, no-transform
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

        id=2

      - |
        POST / HTTP/1.1
        Pragma: no-cache
        Host: {{Hostname}}
        Cache-Control: no-cache, no-transform
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

        id=3

      - |
        POST / HTTP/1.1
        Pragma: no-cache
        Host: {{Hostname}}
        Cache-Control: no-cache, no-transform
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

        id=4

      - |
        POST / HTTP/1.1
        Pragma: no-cache
        Host: {{Hostname}}
        Cache-Control: no-cache, no-transform
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

        id=5

    threads: 5
    race: true

Request comment

The request inline annotation allows the override of the properties / behaviors of each request to be performed. They are very similar to python/java class annotations and must be placed in the request before the RFC line. Currently, only the following overrides are supported:

  • @Host: it covers the real target of the request (usually the host / IP provided as input). It supports syntax with ip/domain, port and scheme, for example: domain tld domain. tld:port http://domain.tld:port
  • @TLS SNI: it will overwrite the SNI name of the TLS request (usually the hostname provided as input). It supports any text, and the special value request.host uses the value of the Host header.
- |
  @Host: https://projectdiscovery.io:443
  POST / HTTP/1.1
  Pragma: no-cache
  Host: {{Hostname}}
  Cache-Control: no-cache, no-transform
  User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0

This is particularly useful. For example, in the case of a template with multiple requests, it is necessary to execute a request after the first request on a specific host (for example, check the API validity):

requests:
  - raw:
      # this request will be sent to {{Hostname}} to get the token
      - |
        GET /getkey HTTP/1.1
        Host: {{Hostname}}

      # This request will be sent instead to https://api.target.com:443 to verify the token validity
      - |
        @Host: https://api.target.com:443
        GET /api/key={{token} HTTP/1.1
        Host: api.target.com:443

    extractors:
      - type: regex
        name: token
        part: body
        regex:
          # random extractor of strings between prefix and suffix
          - 'prefix(.*)suffix'

    matchers:
      - type: word
        part: body
        words:
          - valid token

Tags: security Cyber Security Web Security

Posted by matstuff on Wed, 31 Aug 2022 01:55:27 +0300