Files
gh-agentsecops-secopsagentkit/skills/appsec/dast-nuclei/references/template_development.md
2025-11-29 17:51:02 +08:00

13 KiB

Nuclei Template Development Guide

Table of Contents

Template Structure

Basic Template Anatomy

id: unique-template-id
info:
  name: Human-readable template name
  author: your-name
  severity: critical|high|medium|low|info
  description: Detailed description of what this template detects
  reference:
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-XXXXX
    - https://nvd.nist.gov/vuln/detail/CVE-2024-XXXXX
  tags: cve,owasp,misconfig,custom

# Template type: http, dns, network, file, etc.
http:
  - method: GET
    path:
      - "{{BaseURL}}/vulnerable-endpoint"

    matchers:
      - type: status
        status:
          - 200

      - type: word
        words:
          - "vulnerable signature"

Required Fields

  • id: Unique identifier (kebab-case, organization-scoped for custom templates)
  • info.name: Clear, descriptive name
  • info.author: Template author
  • info.severity: One of: critical, high, medium, low, info
  • info.description: What vulnerability this detects
  • info.tags: Searchable tags for filtering
  • info.reference: Links to CVE, advisories, documentation
  • info.classification: CWE, CVE, OWASP mappings
  • info.metadata: Additional metadata (max-request, verified, etc.)

Template Types

HTTP Templates

Most common template type for web application testing:

id: http-example
info:
  name: HTTP Template Example
  author: security-team
  severity: high
  tags: web,http

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/users"
      - "{{BaseURL}}/api/admin"

    headers:
      Authorization: "Bearer {{token}}"

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

      - type: word
        part: body
        words:
          - "\"role\":\"admin\""
          - "sensitive_data"

    extractors:
      - type: regex
        name: user_ids
        regex:
          - '"id":([0-9]+)'

DNS Templates

Test for DNS misconfigurations and subdomain takeovers:

id: dns-takeover-check
info:
  name: DNS Subdomain Takeover Detection
  author: security-team
  severity: high
  tags: dns,takeover

dns:
  - name: "{{FQDN}}"
    type: CNAME

    matchers:
      - type: word
        words:
          - "amazonaws.com"
          - "azurewebsites.net"
          - "herokuapp.com"

Network Templates

TCP/UDP port scanning and service detection:

id: exposed-redis
info:
  name: Exposed Redis Instance
  author: security-team
  severity: critical
  tags: network,redis,exposure

network:
  - inputs:
      - data: "*1\r\n$4\r\ninfo\r\n"

    host:
      - "{{Hostname}}"
      - "{{Hostname}}:6379"

    matchers:
      - type: word
        words:
          - "redis_version"

Matchers and Extractors

Matcher Types

Status Matcher

matchers:
  - type: status
    status:
      - 200
      - 201
    condition: or

Word Matcher

matchers:
  - type: word
    part: body  # body, header, all
    words:
      - "error"
      - "exception"
    condition: and
    case-insensitive: true

Regex Matcher

matchers:
  - type: regex
    regex:
      - "(?i)password\\s*=\\s*['\"]([^'\"]+)['\"]"
    part: body

Binary Matcher

matchers:
  - type: binary
    binary:
      - "504B0304"  # ZIP file signature (hex)
    part: body

DSL Matcher (Dynamic Expressions)

matchers:
  - type: dsl
    dsl:
      - "status_code == 200 && len(body) > 1000"
      - "contains(tolower(body), 'admin')"

Matcher Conditions

  • and: All matchers must match
  • or: At least one matcher must match (default)
matchers-condition: and
matchers:
  - type: status
    status:
      - 200
  - type: word
    words:
      - "admin"

Extractors

Extract data from responses for reporting or chaining:

Regex Extractor

extractors:
  - type: regex
    name: api_keys
    part: body
    regex:
      - 'api[_-]?key["\s:=]+([a-zA-Z0-9_-]{32,})'
    group: 1

JSON Extractor

extractors:
  - type: json
    name: user_data
    json:
      - ".users[].email"
      - ".users[].id"

XPath Extractor

extractors:
  - type: xpath
    name: titles
    xpath:
      - "//title"

Advanced Techniques

Request Chaining (Workflows)

Execute templates in sequence, passing data between them:

id: workflow-example
info:
  name: Multi-Step Authentication Test
  author: security-team

workflows:
  templates:
    - template: login.yaml
    - template: fetch-user-data.yaml

login.yaml:

id: login-template
info:
  name: Login and Extract Token
  author: security-team
  severity: info

http:
  - method: POST
    path:
      - "{{BaseURL}}/api/login"

    body: '{"username":"test","password":"test"}'

    extractors:
      - type: json
        name: auth_token
        json:
          - ".token"
        internal: true  # Pass to next template

Variables and Helpers

Use dynamic variables and helper functions:

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/users/{{username}}"

    # Available variables:
    # {{BaseURL}}, {{Hostname}}, {{Host}}, {{Port}}, {{Path}}
    # {{RootURL}}, {{Scheme}}, {{username}} (from previous extractor)

    matchers:
      - type: dsl
        dsl:
          # Helper functions: len(), contains(), regex_match(), etc.
          - 'len(body) > 500'
          - 'contains(tolower(header), "x-api-key")'
          - 'status_code >= 200 && status_code < 300'

Payloads and Fuzzing

Use payload files for fuzzing:

id: sqli-fuzzing
info:
  name: SQL Injection Fuzzing
  author: security-team
  severity: critical

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/users?id={{payload}}"

    payloads:
      payload:
        - "1' OR '1'='1"
        - "1' UNION SELECT NULL--"
        - "'; DROP TABLE users--"

    matchers:
      - type: word
        words:
          - "SQL syntax"
          - "mysql_fetch"
          - "ORA-01756"

Or use external payload file:

payloads:
  payload: payloads/sql-injection.txt

attack: clusterbomb  # pitchfork, clusterbomb, batteringram

Rate Limiting and Threads

Control request rate to avoid overwhelming targets:

id: rate-limited-scan
info:
  name: Rate-Limited Vulnerability Scan
  author: security-team
  severity: medium
  metadata:
    max-request: 50  # Maximum requests per template execution

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/endpoint"

    threads: 5  # Concurrent requests (default: 25)

Testing and Validation

Local Testing

Test templates against local test servers:

# Test single template
nuclei -t custom-templates/my-template.yaml -u http://localhost:8080 -debug

# Validate template syntax
nuclei -t custom-templates/my-template.yaml -validate

# Test with verbose output
nuclei -t custom-templates/my-template.yaml -u https://target.com -verbose

Template Validation

Use the bundled validation script:

python3 scripts/template_validator.py custom-templates/my-template.yaml

Test Lab Setup

Create a vulnerable test application for template development:

# Use DVWA (Damn Vulnerable Web Application)
docker run -d -p 80:80 vulnerables/web-dvwa

# Or OWASP Juice Shop
docker run -d -p 3000:3000 bkimminich/juice-shop

Best Practices

1. Accurate Severity Classification

  • Critical: RCE, authentication bypass, full system compromise
  • High: SQL injection, XSS, significant data exposure
  • Medium: Missing security headers, information disclosure
  • Low: Minor misconfigurations, best practice violations
  • Info: Technology detection, non-security findings

2. Minimize False Positives

# Use multiple matchers with AND condition
matchers-condition: and
matchers:
  - type: status
    status:
      - 200

  - type: word
    words:
      - "admin"
      - "dashboard"
    condition: and

  - type: regex
    regex:
      - '<title>.*Admin.*Panel.*</title>'
    case-insensitive: true

3. Clear Naming Conventions

  • id: organization-vulnerability-type-identifier
    • Example: acme-api-key-exposure-config
  • name: Descriptive, clear purpose
    • Example: "ACME Corp API Key Exposure in Config Endpoint"

4. Comprehensive Documentation

info:
  name: Detailed Template Name
  description: |
    Comprehensive description of what this template detects,
    why it's important, and how it works.

    References:
    - CVE-2024-XXXXX
    - Internal ticket: SEC-1234

  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2024-XXXXX
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-XXXXX

  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2024-XXXXX
    cwe-id: CWE-89

  metadata:
    verified: true
    max-request: 10
    shodan-query: 'http.title:"Admin Panel"'

  tags: cve,owasp,sqli,high-severity,verified

5. Responsible Testing Parameters

# Avoid aggressive fuzzing in default templates
info:
  metadata:
    max-request: 10  # Limit total requests

http:
  - method: GET
    threads: 5  # Limit concurrent requests

    # Use specific, targeted payloads
    payloads:
      test: ["safe-payload-1", "safe-payload-2"]

6. Error Handling

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/test"

    # Handle various response scenarios
    matchers:
      - type: dsl
        dsl:
          - "status_code == 200 && contains(body, 'vulnerable')"
          - "status_code == 500 && contains(body, 'error')"
        condition: or

    # Negative matchers (must NOT match)
    matchers:
      - type: word
        negative: true
        words:
          - "404 Not Found"
          - "403 Forbidden"

7. Template Organization

custom-templates/
├── api/
│   ├── api-key-exposure.yaml
│   ├── graphql-introspection.yaml
│   └── rest-api-misconfig.yaml
├── cves/
│   ├── 2024/
│   │   ├── CVE-2024-12345.yaml
│   │   └── CVE-2024-67890.yaml
├── exposures/
│   ├── sensitive-files.yaml
│   └── backup-exposure.yaml
└── misconfig/
    ├── cors-misconfiguration.yaml
    └── debug-mode-enabled.yaml

8. Version Control and Maintenance

  • Use Git to track template changes
  • Tag templates with version numbers in metadata
  • Document changes in template comments
  • Regularly test templates against updated applications
info:
  metadata:
    version: 1.2.0
    last-updated: 2024-11-20
    changelog: |
      1.2.0 - Added additional matcher for new vulnerability variant
      1.1.0 - Improved regex pattern to reduce false positives
      1.0.0 - Initial release

Example: Complete Custom Template

id: acme-corp-api-debug-exposure
info:
  name: ACME Corp API Debug Endpoint Exposure
  author: acme-security-team
  severity: high
  description: |
    Detects exposed debug endpoint in ACME Corp API that leaks
    sensitive configuration including database credentials,
    API keys, and internal service URLs.

  reference:
    - https://internal-wiki.acme.com/security/SEC-1234

  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
    cvss-score: 7.5
    cwe-id: CWE-200

  metadata:
    verified: true
    max-request: 3
    version: 1.0.0

  tags: acme,api,exposure,debug,high-severity

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v1/debug/config"
      - "{{BaseURL}}/api/v2/debug/config"
      - "{{BaseURL}}/debug/config"

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

      - type: word
        part: body
        words:
          - "database_url"
          - "api_secret_key"
        condition: or

      - type: regex
        part: body
        regex:
          - '"(password|secret|token)":\s*"[^"]+"'

    extractors:
      - type: regex
        name: exposed_secrets
        part: body
        regex:
          - '"(database_url|api_secret_key|jwt_secret)":\s*"([^"]+)"'
        group: 2

      - type: json
        name: config_data
        json:
          - ".database_url"
          - ".api_secret_key"

Resources