Crafting Custom Nuclei Templates for Automated API Vulnerability Discovery

Crafting Custom Nuclei Templates for Automated API Vulnerability Discovery

Leveraging custom Nuclei templates provides a direct, powerful method for uncovering API vulnerabilities with precision. The default Nuclei template set is extensive, but many API-specific flaws require tailored logic that reflects unique application behaviors and data structures. This direct approach allows penetration testers to codify specific attack patterns observed during manual testing or derived from API documentation, integrating them into an automated discovery pipeline.

The Nuclei Template Anatomy for API Reconnaissance

A Nuclei template is fundamentally a YAML file describing an HTTP request, conditions for a match, and optional data extraction. For API vulnerability discovery, the HTTP request block is paramount, allowing fine-grained control over method, path, headers, and body content.

The core components of an API-focused template include:

  • id: A unique identifier for the template.
  • info: Metadata like name, author, severity, and description. This is crucial for organization and reporting.
  • requests: Defines the actual HTTP interaction.
  • matchers: Specifies conditions that, if met, indicate a vulnerability or interesting finding.
  • extractors: Captures specific data from the response for further analysis or chaining.

Basic HTTP Request Structure

The `requests` block is where the magic happens. We often leverage placeholders like `{{BaseURL}}` which Nuclei replaces with the target URL provided at runtime. For API testing, defining custom headers like `Content-Type: application/json` or `Authorization: Bearer ` is critical.

id: api-info-disclosure-v1
info:
  name: API Endpoint Information Disclosure
  author: pentester
  severity: low
  description: Checks for common sensitive information disclosure on an API endpoint.
  tags: api, info, disclosure

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v1/users/me"
      - "{{BaseURL}}/api/internal/config"
    headers:
      User-Agent: Nuclei/pentest-bot
      Accept: application/json

    matchers-condition: or
    matchers:
      - type: regex
        part: body
        regex:
          - '(?i)api_key[\'"]?:\s*[\'"]?[a-zA-Z0-9]{32,64}[\'"]?'
          - '(?i)secret_key[\'"]?:\s*[\'"]?[a-zA-Z0-9]{32,64}[\'"]?'
        condition: or
        description: "Found potential API or secret key"

      - type: status
        status:
          - 200
        description: "Endpoint responded with 200 OK, further manual inspection may be needed."
This template probes two common API paths for potential information disclosure. The `matchers-condition: or` ensures that if either a regex match *or* a 200 status code is returned, Nuclei flags it. The regex specifically looks for patterns resembling API or secret keys within the response body.

Dynamic Payloads and Fuzzing

One of Nuclei's strengths for API testing is its ability to integrate dynamic payloads. The `payloads` and `fuzzing` keywords enable iterating through lists of values, making it ideal for testing IDORs, parameter manipulation, or brute-forcing.

id: api-idor-user-enum
info:
  name: API IDOR User Enumeration
  author: pentester
  severity: medium
  description: Tests for Insecure Direct Object Reference (IDOR) by enumerating user IDs.
  tags: api, idor, auth, enum

payloads:
  user_ids:
    - "1"
    - "2"
    - "3"
    - "4"
    - "5"
    - "999" # Potential admin or higher privilege ID

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v2/users/{{user_ids}}" # Payload injected here
    headers:
      User-Agent: Nuclei/pentest-bot
      Accept: application/json
      Authorization: Bearer {{token_placeholder}} # Replace with valid token for auth bypass tests

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
        description: "Successful response for user ID."

      - type: word
        part: body
        words:
          - '"id": "{{user_ids}}"' # Verify the requested ID is in the response
        negative: false
        description: "Confirmed user ID in response."

      - type: word
        part: body
        words:
          - 'Unauthorized'
          - 'Access Denied'
        negative: true # Ensure these words are NOT present
        condition: or
        description: "No explicit authorization error."
In this IDOR example, the `user_ids` payload is iterated for each request, dynamically changing the path. The matchers check for a `200` status, and crucially, confirm that the requested `user_id` is present in the response while also ensuring explicit authorization errors are absent. This pattern is effective for discovering object enumeration or unauthorized data access. For more comprehensive web security testing and to integrate custom findings into broader workflows, platforms like Secably can consume Nuclei results, providing centralized vulnerability management.

Case Study: Identifying Unauthenticated Endpoints

Many APIs expose internal or sensitive endpoints that are intended to be protected but sometimes lack proper authentication checks. Crafting templates to systematically probe for these is a common task. Before targeting, internet-wide reconnaissance tools like Zondex can help identify public-facing API gateways or hidden subdomains that might host these services.

id: api-unauthenticated-admin-panel
info:
  name: Unauthenticated Admin API Endpoint
  author: pentester
  severity: critical
  description: Checks for direct access to common admin API endpoints without authentication.
  tags: api, unauth, admin, critical

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v1/admin/users"
      - "{{BaseURL}}/api/v1/admin/logs"
      - "{{BaseURL}}/api/v1/admin/health"
    headers:
      User-Agent: Nuclei/pentest-bot
      Accept: application/json

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
        description: "Endpoint responded with 200 OK."

      - type: word
        part: body
        words:
          - '"admin": true'
          - '"users":'
          - '"logs":'
        condition: or
        description: "Contains admin-related keywords or user/log data."

      - type: word
        part: body
        words:
          - 'Unauthorized'
          - 'Authentication Required'
          - 'Forbidden'
        negative: true
        condition: or
        description: "No authentication required error message."
This template iterates through common admin paths. The matchers confirm a `200 OK` status, look for keywords indicative of administrative data, and critically, ensure that common authentication failure messages are *not* present. This combined logic reduces false positives significantly.

Extracting Data for Chaining and Reporting

Extractors are invaluable for capturing specific pieces of information from API responses. This data can then be used for further requests in a workflow (chaining) or simply for reporting. Common extractor types include `regex` and `json`.

id: api-extract-session-token
info:
  name: API Session Token Extraction
  author: pentester
  severity: info
  description: Extracts session tokens from API login responses.
  tags: api, session, extraction

http:
  - method: POST
    path:
      - "{{BaseURL}}/api/v1/auth/login"
    headers:
      Content-Type: application/json
    body: |
      {
        "username": "testuser",
        "password": "testpassword"
      }

    matchers:
      - type: status
        status:
          - 200

    extractors:
      - type: json
        json:
          - '$.data.session_token'
        name: session_token
        description: "Extracted session token from login response."

      - type: regex
        regex:
          - 'sessionToken":\s*"(.*?)"'
        name: session_token_fallback
        description: "Fallback regex for session token extraction."
Here, after a mock login attempt, Nuclei attempts to extract a `session_token` using a JSON path `$.data.session_token`. A fallback regex is also included for robustness, handling cases where the JSON structure might vary or a token might appear outside the expected path. This extracted token could then be passed to subsequent requests in a more complex Nuclei workflow to test authenticated endpoints.

Running Custom Templates and Observing Output

Executing custom Nuclei templates is straightforward. The `-t` flag specifies the template(s), and `-u` (or `-l` for a list of URLs) defines the target(s).

# Run a single custom template against a target
nuclei -t custom-templates/api-idor-user-enum.yaml -u https://api.example.com

# Run all templates in a directory against a list of targets
nuclei -t custom-templates/api/ -l targets.txt -o nuclei_api_results.txt -json

# Example output snippet (simplified)
# [api-idor-user-enum] https://api.example.com/api/v2/users/3 - [200 OK]
# [api-info-disclosure-v1] https://api.example.com/api/v1/users/me - [200 OK] - Found potential API or secret key
The `-json` flag is particularly useful for programmatic parsing of results, which can be integrated into CI/CD pipelines or custom reporting tools. When testing APIs, especially those with rate limiting or IP-based restrictions, routing traffic through proxies can be essential. Tools like GProxy can be configured to forward Nuclei's traffic, allowing for geographically diverse testing or obfuscating the origin IP address during engagements. This can prevent blacklisting and ensure comprehensive scan coverage. Crafting custom Nuclei templates provides pentesters with a highly adaptable and efficient mechanism for automating API vulnerability discovery. It moves beyond generic scanners, allowing for deep, application-specific testing that mirrors a manual penetration test's logic but at an automated scale.