# Nuclei Template Development Guide ## Table of Contents - [Template Structure](#template-structure) - [Template Types](#template-types) - [Matchers and Extractors](#matchers-and-extractors) - [Advanced Techniques](#advanced-techniques) - [Testing and Validation](#testing-and-validation) - [Best Practices](#best-practices) ## Template Structure ### Basic Template Anatomy ```yaml 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 ### Optional but Recommended Fields - **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: ```yaml 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: ```yaml 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: ```yaml 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 ```yaml matchers: - type: status status: - 200 - 201 condition: or ``` #### Word Matcher ```yaml matchers: - type: word part: body # body, header, all words: - "error" - "exception" condition: and case-insensitive: true ``` #### Regex Matcher ```yaml matchers: - type: regex regex: - "(?i)password\\s*=\\s*['\"]([^'\"]+)['\"]" part: body ``` #### Binary Matcher ```yaml matchers: - type: binary binary: - "504B0304" # ZIP file signature (hex) part: body ``` #### DSL Matcher (Dynamic Expressions) ```yaml 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) ```yaml matchers-condition: and matchers: - type: status status: - 200 - type: word words: - "admin" ``` ### Extractors Extract data from responses for reporting or chaining: #### Regex Extractor ```yaml extractors: - type: regex name: api_keys part: body regex: - 'api[_-]?key["\s:=]+([a-zA-Z0-9_-]{32,})' group: 1 ``` #### JSON Extractor ```yaml extractors: - type: json name: user_data json: - ".users[].email" - ".users[].id" ``` #### XPath Extractor ```yaml extractors: - type: xpath name: titles xpath: - "//title" ``` ## Advanced Techniques ### Request Chaining (Workflows) Execute templates in sequence, passing data between them: ```yaml id: workflow-example info: name: Multi-Step Authentication Test author: security-team workflows: templates: - template: login.yaml - template: fetch-user-data.yaml ``` **login.yaml**: ```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: ```yaml 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: ```yaml 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: ```yaml payloads: payload: payloads/sql-injection.txt attack: clusterbomb # pitchfork, clusterbomb, batteringram ``` ### Rate Limiting and Threads Control request rate to avoid overwhelming targets: ```yaml 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: ```bash # 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: ```bash python3 scripts/template_validator.py custom-templates/my-template.yaml ``` ### Test Lab Setup Create a vulnerable test application for template development: ```bash # 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 ```yaml # Use multiple matchers with AND condition matchers-condition: and matchers: - type: status status: - 200 - type: word words: - "admin" - "dashboard" condition: and - type: regex regex: - '