Added new YAML based doc to structures

dev
Ice3man543 2021-07-27 16:03:56 +05:30
parent 543cfdd309
commit d04511494d
12 changed files with 478 additions and 98 deletions

View File

@ -4,28 +4,70 @@ import "regexp"
// Extractor is used to extract part of response using a regex. // Extractor is used to extract part of response using a regex.
type Extractor struct { type Extractor struct {
// Name is the extractor's name // description: |
// Name of the extractor. Name should be lowercase and must not contain
// spaces or dashes (-).
// examples:
// - value: "\"cookie-extractor\""
Name string `yaml:"name,omitempty"` Name string `yaml:"name,omitempty"`
// Type is the type of the extractor // description: |
// Type is the type of the extractor.
// values:
// - "regex"
// - "kval"
Type string `yaml:"type"` Type string `yaml:"type"`
// extractorType is the internal type of the extractor // extractorType is the internal type of the extractor
extractorType ExtractorType extractorType ExtractorType
// Regex are the regex pattern required to be present in the response // description: |
// Regex contains the regular expression patterns to exract from a part.
//
// Go regex engine does not supports lookaheads or lookbehinds, so as a result
// they are also not supported in nuclei.
// examples:
// - name: Braintree Access Token Regex
// value: >
// []string{"access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}"}
// - name: Wordpress Author Extraction regex
// value: >
// []string{"Author:(?:[A-Za-z0-9 -\\_=\"]+)?<span(?:[A-Za-z0-9 -\\_=\"]+)?>([A-Za-z0-9]+)<\\/span>"}
Regex []string `yaml:"regex"` Regex []string `yaml:"regex"`
// RegexGroup specifies a group to extract from the regex // description: |
// Group specifies a numbered group to extract from the regex.
// examples:
// - name: Example Regex Group
// - value: "1"
RegexGroup int `yaml:"group"` RegexGroup int `yaml:"group"`
// regexCompiled is the compiled variant // regexCompiled is the compiled variant
regexCompiled []*regexp.Regexp regexCompiled []*regexp.Regexp
// KVal are the kval to be present in the response headers/cookies // description: |
// kval contains the key-value pairs required in the response.
//
// Each protocol exposes a lot of different data in response. The kval
// extractor can be used to extract those key-value pairs. A list of
// supported parts is available in docs for request types.
// examples:
// - name: Extract Server Header From HTTP Response
// value: >
// []string{"Server"}
// - name: Extracting value of PHPSESSID Cookie
// value: >
// []string{"PHPSESSID"}
KVal []string `yaml:"kval,omitempty"` KVal []string `yaml:"kval,omitempty"`
// Part is the part of the request to match // description: |
// Part is the part of the request response to extract data from.
// //
// By default, matching is performed in request body. // Each protocol exposes a lot of different parts which are well
// documented in docs for each request type.
// examples:
// - value: "\"body\""
// - value: "\"raw\""
Part string `yaml:"part,omitempty"` Part string `yaml:"part,omitempty"`
// Internal defines if this is used internally // description: |
// Internal, when set to true will allow using the value extracted
// in the next request for some protocols (like HTTP).
Internal bool `yaml:"internal,omitempty"` Internal bool `yaml:"internal,omitempty"`
} }

View File

@ -8,35 +8,102 @@ import (
// Matcher is used to match a part in the output from a protocol. // Matcher is used to match a part in the output from a protocol.
type Matcher struct { type Matcher struct {
// Type is the type of the matcher // description: |
// Type is the type of the matcher.
// values:
// - "status"
// - "size"
// - "word"
// - "regex"
// - "binary"
// - "dsl"
Type string `yaml:"type"` Type string `yaml:"type"`
// Condition is the optional condition between two matcher variables // description: |
// // Condition is the optional condition between two matcher variables. By default,
// By default, the condition is assumed to be OR. // the condition is assumed to be OR.
// values:
// - "and"
// - "or"
Condition string `yaml:"condition,omitempty"` Condition string `yaml:"condition,omitempty"`
// Part is the part of the data to match // description: |
// Part is the part of the request response to match data from.
//
// Each protocol exposes a lot of different parts which are well
// documented in docs for each request type.
// examples:
// - value: "\"body\""
// - value: "\"raw\""
Part string `yaml:"part,omitempty"` Part string `yaml:"part,omitempty"`
// Negative specifies if the match should be reversed // description: |
// It will only match if the condition is not true. // Negative specifies if the match should be reversed
// It will only match if the condition is not true.
Negative bool `yaml:"negative,omitempty"` Negative bool `yaml:"negative,omitempty"`
// Name is matcher Name // description: |
// Name of the matcher. Name should be lowercase and must not contain
// spaces or dashes (-).
// examples:
// - value: "\"cookie-matcher\""
Name string `yaml:"name,omitempty"` Name string `yaml:"name,omitempty"`
// Status are the acceptable status codes for the response // description: |
// Status are the acceptable status codes for the response.
// examples:
// - value: >
// []int{200, 302}
Status []int `yaml:"status,omitempty"` Status []int `yaml:"status,omitempty"`
// Size is the acceptable size for the response // description: |
// Size is the acceptable size for the response
// examples:
// - value: >
// []int{3029, 2042}
Size []int `yaml:"size,omitempty"` Size []int `yaml:"size,omitempty"`
// Words are the words required to be present in the response // description: |
// Words contains word patterns required to be present in the response part.
// examples:
// - name: Match for outlook mail protection domain
// value: >
// []string{"mail.protection.outlook.com"}
// - name: Match for application/json in response headers
// value: >
// []string{"application/json"}
Words []string `yaml:"words,omitempty"` Words []string `yaml:"words,omitempty"`
// Regex are the regex pattern required to be present in the response // description: |
// Regex contains Regular Expression patterns required to be present in the response part.
// examples:
// - name: Match for Linkerd Service via Regex
// value: >
// []string{`(?mi)^Via\\s*?:.*?linkerd.*$`}
// - name: Match for Open Redirect via Location header
// value: >
// []string{`(?m)^(?:Location\\s*?:\\s*?)(?:https?://|//)?(?:[a-zA-Z0-9\\-_\\.@]*)example\\.com.*$`}
Regex []string `yaml:"regex,omitempty"` Regex []string `yaml:"regex,omitempty"`
// Binary are the binary characters required to be present in the response // description: |
// Binary are the binary patterns required to be present in the response part.
// examples:
// - name: Match for Springboot Heapdump Actuator "JAVA PROFILE", "HPROF", "Gunzip magic byte"
// value: >
// []string{"4a4156412050524f46494c45", "4850524f46", "1f8b080000000000"}
// - name: Match for 7zip files
// value: >
// []string{"377ABCAF271C"}
Binary []string `yaml:"binary,omitempty"` Binary []string `yaml:"binary,omitempty"`
// DSL are the dsl queries // description: |
// DSL are the dsl expressions that will be evaluated as part of nuclei matching rules.
// A list of these helper functions are available [here](https://nuclei.projectdiscovery.io/templating-guide/helper-functions/).
// examples:
// - name: DSL Matcher for package.json file
// value: >
// []string{"contains(body, 'packages') && contains(tolower(all_headers), 'application/octet-stream') && status_code == 200"}
// - name: DSL Matcher for missing strict transport security header
// value: >
// []string{"!contains(tolower(all_headers), ''strict-transport-security'')"}
DSL []string `yaml:"dsl,omitempty"` DSL []string `yaml:"dsl,omitempty"`
// Encoding specifies the encoding for the word content if any. // description: |
// Encoding specifies the encoding for the words field if any.
// values:
// - "hex"
Encoding string `yaml:"encoding,omitempty"` Encoding string `yaml:"encoding,omitempty"`
// cached data for the compiled matcher // cached data for the compiled matcher

View File

@ -8,14 +8,23 @@ import (
// Operators contains the operators that can be applied on protocols // Operators contains the operators that can be applied on protocols
type Operators struct { type Operators struct {
// Matchers contains the detection mechanism for the request to identify // description: |
// whether the request was successful // Matchers contains the detection mechanism for the request to identify
// whether the request was successful by doing pattern matching
// on request/responses.
//
// Multiple matchers can be combined together with `matcher-condition` flag
// which accepts either `and` or `or` as argument.
Matchers []*matchers.Matcher `yaml:"matchers,omitempty"` Matchers []*matchers.Matcher `yaml:"matchers,omitempty"`
// Extractors contains the extraction mechanism for the request to identify // description: |
// and extract parts of the response. // Extractors contains the extraction mechanism for the request to identify
// and extract parts of the response.
Extractors []*extractors.Extractor `yaml:"extractors,omitempty"` Extractors []*extractors.Extractor `yaml:"extractors,omitempty"`
// MatchersCondition is the condition of the matchers // description: |
// whether to use AND or OR. Default is OR. // MatchersCondition is the condition between the matchers. Default is OR.
// values:
// - "and"
// - "or"
MatchersCondition string `yaml:"matchers-condition,omitempty"` MatchersCondition string `yaml:"matchers-condition,omitempty"`
// cached variables that may be used along with request. // cached variables that may be used along with request.
matchersCondition matchers.ConditionType matchersCondition matchers.ConditionType

View File

@ -20,13 +20,42 @@ type Request struct {
ID string `yaml:"id"` ID string `yaml:"id"`
// Path contains the path/s for the request // description: |
// Name is the Hostname to make DNS request for.
//
// Generally, it is set to {{FQDN}} which is the domain we get from input.
// examples:
// - value: "\"{{FQDN}}\""
Name string `yaml:"name"` Name string `yaml:"name"`
// Type is the type of DNS request to make // description: |
// Type is the type of DNS request to make.
// values:
// - "A"
// - "NS"
// - "CNAME"
// - "SOA"
// - "PTR"
// - "MX"
// - "TXT"
// - "AAAA"
Type string `yaml:"type"` Type string `yaml:"type"`
// Class is the class of the DNS request // description: |
// Class is the class of the DNS request.
//
// Usually it's enough to just leave it as INET.
// values:
// - "INET"
// - "CSNET"
// - "CHAOS"
// - "HESIOD"
// - "NONE"
// - "ANY"
Class string `yaml:"class"` Class string `yaml:"class"`
// Retries is the number of retries for the DNS request // description: |
// Retries is the number of retries for the DNS request
// examples:
// - name: Use a retry of 3 to 5 generally
// value: 5
Retries int `yaml:"retries"` Retries int `yaml:"retries"`
CompiledOperators *operators.Operators CompiledOperators *operators.Operators
@ -37,7 +66,8 @@ type Request struct {
class uint16 class uint16
question uint16 question uint16
// Recursion specifies whether to recurse all the answers. // description: |
// Recursion determines if resolver should recurse all records to get fresh results.
Recursion bool `yaml:"recursion"` Recursion bool `yaml:"recursion"`
} }

View File

@ -12,16 +12,29 @@ import (
type Request struct { type Request struct {
// Operators for the current request go here. // Operators for the current request go here.
operators.Operators `yaml:",inline"` operators.Operators `yaml:",inline"`
// Extensions is the list of extensions to perform matching on. // description: |
// Extensions is the list of extensions to perform matching on.
// examples:
// - value: '[]string{".txt", ".go", ".json"}'
Extensions []string `yaml:"extensions"` Extensions []string `yaml:"extensions"`
// ExtensionDenylist is the list of file extensions to deny during matching. // description: |
// ExtensionDenylist is the list of file extensions to deny during matching.
//
// By default, it contains some non-interesting extensions that are hardcoded
// in nuclei.
// examples:
// - value: '[]string{".avi", ".mov", ".mp3"}'
ExtensionDenylist []string `yaml:"denylist"` ExtensionDenylist []string `yaml:"denylist"`
ID string `yaml:"id"` ID string `yaml:"id"`
// MaxSize is the maximum size of the file to run request on. // description: |
// By default, nuclei will process 5MB files and not go more than that. // MaxSize is the maximum size of the file to run request on.
// It can be set to much lower or higher depending on use. //
// By default, nuclei will process 5MB files and not go more than that.
// It can be set to much lower or higher depending on use.
// examples:
// - value: 2048
MaxSize int `yaml:"max-size"` MaxSize int `yaml:"max-size"`
CompiledOperators *operators.Operators CompiledOperators *operators.Operators
@ -30,7 +43,8 @@ type Request struct {
extensions map[string]struct{} extensions map[string]struct{}
extensionDenylist map[string]struct{} extensionDenylist map[string]struct{}
// NoRecursive specifies whether to not do recursive checks if folders are provided. // description: |
// NoRecursive specifies whether to not do recursive checks if folders are provided.
NoRecursive bool `yaml:"no-recursive"` NoRecursive bool `yaml:"no-recursive"`
allExtensions bool allExtensions bool

View File

@ -109,10 +109,46 @@ var ActionToActionString = map[ActionType]string{
// are discovered on the found page. We also keep track and only // are discovered on the found page. We also keep track and only
// scrape new navigation from pages we haven't crawled yet. // scrape new navigation from pages we haven't crawled yet.
type Action struct { type Action struct {
Data map[string]string `yaml:"args,omitempty"` // description:
Name string `yaml:"name,omitempty"` // Args contain arguments for the headless action.
Description string `yaml:"description,omitempty"` //
ActionType string `yaml:"action"` // Per action arguments are described in detail [here](https://nuclei.projectdiscovery.io/templating-guide/protocols/headless/).
Data map[string]string `yaml:"args,omitempty"`
// description: |
// Name is the name assigned to the headless action.
//
// This can be used to execute code, for instance in browser
// DOM using script action, and get the result in a variable
// which can be matched upon by nuclei. An Example template [here](https://github.com/projectdiscovery/nuclei-templates/blob/master/headless/prototype-pollution-check.yaml).
Name string `yaml:"name,omitempty"`
// description: |
// Description is the optional description of the headless action
Description string `yaml:"description,omitempty"`
// description: |
// Action is the type of the action to perform.
// values:
// - "navigate"
// - "script"
// - "click"
// - "rightclick"
// - "text"
// - "screenshot"
// - "time"
// - "select"
// - "files"
// - "waitload"
// - "getresource"
// - "extract"
// - "setmethod"
// - "addheader"
// - "setheader"
// - "deleteheader"
// - "setbody"
// - "waitevent"
// - "keyboard"
// - "debug"
// - "sleep"
ActionType string `yaml:"action"`
} }
// String returns the string representation of an action // String returns the string representation of an action

View File

@ -11,7 +11,8 @@ import (
type Request struct { type Request struct {
ID string `yaml:"id"` ID string `yaml:"id"`
// Steps is the list of actions to run for headless request // description: |
// Steps is the list of actions to run for headless request
Steps []*engine.Action `yaml:"steps"` Steps []*engine.Action `yaml:"steps"`
// Operators for the current request go here. // Operators for the current request go here.

View File

@ -16,36 +16,110 @@ import (
type Request struct { type Request struct {
// Operators for the current request go here. // Operators for the current request go here.
operators.Operators `yaml:",inline"` operators.Operators `yaml:",inline"`
// Path contains the path/s for the request // description: |
// Path contains the path/s for the HTTP requests. It supports variables
// as placeholders.
// examples:
// - name: Some example path values
// value: >
// []string{"{{BaseURL}}", "{{BaseURL}}/+CSCOU+/../+CSCOE+/files/file_list.json?path=/sessions"}
Path []string `yaml:"path"` Path []string `yaml:"path"`
// Raw contains raw requests // description: |
// Raw contains HTTP Requests in Raw format.
// examples:
// - name: Some example raw requests
// value: |
// []string{"GET /etc/passwd HTTP/1.1\nHost:\nContent-Length: 4", "POST /.%0d./.%0d./.%0d./.%0d./bin/sh HTTP/1.1\nHost: {{Hostname}}\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0\nContent-Length: 1\nConnection: close\n\necho\necho\ncat /etc/passwd 2>&1"}
Raw []string `yaml:"raw"` Raw []string `yaml:"raw"`
ID string `yaml:"id"` // docgen:nodoc
// Name is the name of the request ID string `yaml:"-"`
// description: |
// Name is the optional name of the request.
//
// If a name is specified, all the named request in a template can be matched upon
// in a combined manner allowing multirequest based matchers.
Name string `yaml:"Name"` Name string `yaml:"Name"`
// AttackType is the attack type // description: |
// Sniper, PitchFork and ClusterBomb. Default is Sniper // Attack is the type of payload combinations to perform.
//
// Sniper is each payload once, pitchfork combines multiple payload sets and clusterbomb generates
// permutations and combinations for all payloads.
// values:
// - "sniper"
// - "pitchfork"
// - "clusterbomb"
AttackType string `yaml:"attack"` AttackType string `yaml:"attack"`
// Method is the request method, whether GET, POST, PUT, etc // description: |
// Method is the HTTP Request Method.
// values:
// - "GET"
// - "POST"
// - "PUT"
// - "DELETE"
Method string `yaml:"method"` Method string `yaml:"method"`
// Body is an optional parameter which contains the request body for POST methods, etc // description: |
// Body is an optional parameter which contains HTTP Request body.
// examples:
// - name: Same Body for a Login POST request
// value: "\"username=test&password=test\""
Body string `yaml:"body"` Body string `yaml:"body"`
// Path contains the path/s for the request variables // description: |
// Payloads contains any payloads for the current request.
//
// Payloads support both key-values combinations where a list
// of payloads is provided, or optionally a single file can also
// be provided as payload which will be read on run-time.
// examples:
// - name: A payload list for Tomcat Bruteforce
// value: exampleTomcatUserPassPayload
// - name: A payload example of reading from file
// value: exampleFileBasedPayload
Payloads map[string]interface{} `yaml:"payloads"` Payloads map[string]interface{} `yaml:"payloads"`
// Headers contains headers to send with the request // description: |
// Headers contains HTTP Headers to send with the request.
// examples:
// - value: |
// map[string]string{"Content-Type": "application/x-www-form-urlencoded", "Content-Length": "1", "Any-Header": "Any-Value"}
Headers map[string]string `yaml:"headers"` Headers map[string]string `yaml:"headers"`
// RaceNumberRequests is the number of same request to send in race condition attack // description: |
// RaceCount is the number of times to send a request in Race Condition Attack.
// examples:
// - name: Send a request 5 times
// value: "5"
RaceNumberRequests int `yaml:"race_count"` RaceNumberRequests int `yaml:"race_count"`
// MaxRedirects is the maximum number of redirects that should be followed. // description: |
// MaxRedirects is the maximum number of redirects that should be followed.
// examples:
// - name: Follow upto 5 redirects
// value: "5"
MaxRedirects int `yaml:"max-redirects"` MaxRedirects int `yaml:"max-redirects"`
// PipelineConcurrentConnections is number of connections in pipelining // description: |
// PipelineConcurrentConnections is number of connections to create during pipelining.
// examples:
// - name: Create 40 concurrent connections
// value: 40
PipelineConcurrentConnections int `yaml:"pipeline-concurrent-connections"` PipelineConcurrentConnections int `yaml:"pipeline-concurrent-connections"`
// PipelineRequestsPerConnection is number of requests in pipelining // description: |
// PipelineRequestsPerConnection is number of requests to send per connection when pipelining.
// examples:
// - name: Send 100 requests per pipeline connection
// value: 100
PipelineRequestsPerConnection int `yaml:"pipeline-requests-per-connection"` PipelineRequestsPerConnection int `yaml:"pipeline-requests-per-connection"`
// Threads specifies number of threads for sending requests // description: |
// Threads specifies number of threads to use sending requests. This enables Connection Pooling.
//
// Connection: Close attribute must not be used in request while using threads flag, otherwise
// pooling will fail and engine will continue to close connections after requests.
// examples:
// - name: Send requests using 10 concurrent threads
// value: 10
Threads int `yaml:"threads"` Threads int `yaml:"threads"`
// MaxSize is the maximum size of http response body to read in bytes. // description: |
// MaxSize is the maximum size of http response body to read in bytes.
// examples:
// - name: Read max 2048 bytes of the response
// value: 2048
MaxSize int `yaml:"max-size"` MaxSize int `yaml:"max-size"`
CompiledOperators *operators.Operators CompiledOperators *operators.Operators
@ -57,21 +131,36 @@ type Request struct {
generator *generators.Generator // optional, only enabled when using payloads generator *generators.Generator // optional, only enabled when using payloads
httpClient *retryablehttp.Client httpClient *retryablehttp.Client
rawhttpClient *rawhttp.Client rawhttpClient *rawhttp.Client
// CookieReuse is an optional setting that makes cookies shared within requests
// description: |
// CookieReuse is an optional setting that enables cookie reuse for
// all requests defined in raw section.
CookieReuse bool `yaml:"cookie-reuse"` CookieReuse bool `yaml:"cookie-reuse"`
// Redirects specifies whether redirects should be followed. // description: |
// Redirects specifies whether redirects should be followed by the HTTP Client.
//
// This can be used in conjunction with `max-redirects` to control the HTTP request redirects.
Redirects bool `yaml:"redirects"` Redirects bool `yaml:"redirects"`
// Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining (race conditions/billions requests) // description: |
// All requests must be indempotent (GET/POST) // Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining
//
// All requests must be indempotent (GET/POST). This can be used for race conditions/billions requests.
Pipeline bool `yaml:"pipeline"` Pipeline bool `yaml:"pipeline"`
// Specify in order to skip request RFC normalization // description: |
// Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests.
//
// This uses the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine to achieve complete
// control over the request, with no normalization performed by the client.
Unsafe bool `yaml:"unsafe"` Unsafe bool `yaml:"unsafe"`
// Race determines if all the request have to be attempted at the same time // description: |
// The minimum number of requests is determined by threads // Race determines if all the request have to be attempted at the same time (Race Condition)
//
// The actual number of requests that will be sent is determined by the `race_count` field.
Race bool `yaml:"race"` Race bool `yaml:"race"`
// ReqCondition automatically assigns numbers to requests and preserves // description: |
// their history for being matched at the end. // ReqCondition automatically assigns numbers to requests and preserves their history.
// Currently only works with sequential http requests. //
// This allows matching on them later for multi-request conditions.
ReqCondition bool `yaml:"req-condition"` ReqCondition bool `yaml:"req-condition"`
} }

View File

@ -14,7 +14,6 @@ func TestHTTPCompile(t *testing.T) {
testutils.Init(options) testutils.Init(options)
templateID := "testing-http" templateID := "testing-http"
request := &Request{ request := &Request{
ID: templateID,
Name: "testing", Name: "testing",
Payloads: map[string]interface{}{ Payloads: map[string]interface{}{
"username": []string{"admin"}, "username": []string{"admin"},

View File

@ -17,19 +17,44 @@ import (
type Request struct { type Request struct {
ID string `yaml:"id"` ID string `yaml:"id"`
// Address is the address to send requests to (host:port:tls combos generally) // description: |
// Address is the address to send requests to.
//
// Usually it's set to `{{Hostname}}`. If you want to enable TLS for
// TCP Connection, you can use `tls://{{Hostname}}`.
// examples:
// - value: |
// []string{"{{Hostname}}"}
Address []string `yaml:"host"` Address []string `yaml:"host"`
addresses []addressKV addresses []addressKV
// AttackType is the attack type // description: |
// Sniper, PitchFork and ClusterBomb. Default is Sniper // Attack is the type of payload combinations to perform.
//
// Sniper is each payload once, pitchfork combines multiple payload sets and clusterbomb generates
// permutations and combinations for all payloads.
// values:
// - "sniper"
// - "pitchfork"
// - "clusterbomb"
AttackType string `yaml:"attack"` AttackType string `yaml:"attack"`
// Path contains the path/s for the request variables // description: |
// Payloads contains any payloads for the current request.
//
// Payloads support both key-values combinations where a list
// of payloads is provided, or optionally a single file can also
// be provided as payload which will be read on run-time.
Payloads map[string]interface{} `yaml:"payloads"` Payloads map[string]interface{} `yaml:"payloads"`
// Payload is the payload to send for the network request // description: |
// Inputs contains inputs for the network socket
Inputs []*Input `yaml:"inputs"` Inputs []*Input `yaml:"inputs"`
// ReadSize is the size of response to read (1024 if not provided by default) // description: |
// ReadSize is the size of response to read at the end
//
// Default value for read-size is 1024.
// examples:
// - value: "2048"
ReadSize int `yaml:"read-size"` ReadSize int `yaml:"read-size"`
// Operators for the current request go here. // Operators for the current request go here.
@ -51,13 +76,37 @@ type addressKV struct {
// Input is the input to send on the network // Input is the input to send on the network
type Input struct { type Input struct {
// Data is the data to send as the input // description: |
// Data is the data to send as the input.
//
// It supports DSL Helper Functions as well as normal expressions.
// examples:
// - value: "\"TEST\""
// - value: "\"hex_decode('50494e47')\""
Data string `yaml:"data"` Data string `yaml:"data"`
// Type is the type of input - hex, text. // description: |
// Type is the type of input specified in `data` field.
//
// Default value is text, but hex can be used for hex formatted data.
// values:
// - "hex"
// - "text"
Type string `yaml:"type"` Type string `yaml:"type"`
// Read is the number of bytes to read from socket // description: |
// Read is the number of bytes to read from socket.
//
// This can be used for protcols which expected an immediate response. You can
// read and write responses one after another and evetually perform matching
// on every data captured with `name` attribute.
//
// The [network docs](https://nuclei.projectdiscovery.io/templating-guide/protocols/network/) highlight more on how to do this.
// examples:
// - value: "1024"
Read int `yaml:"read"` Read int `yaml:"read"`
// Name is the optional name of the input to provide matching on // description: |
// Name is the optional name of the data read to provide matching on.
// examples:
// - value: "\"prefix\""
Name string `yaml:"name"` Name string `yaml:"name"`
} }

View File

@ -10,24 +10,56 @@ import (
"github.com/projectdiscovery/nuclei/v2/pkg/workflows" "github.com/projectdiscovery/nuclei/v2/pkg/workflows"
) )
// Template is a request template parsed from a yaml file var (
exampleTomcatUserPassPayload = map[string]interface{}{
"username": []string{"tomcat", "admin"},
"password": []string{"tomcat", "admin", "password"},
}
exampleFileBasedPayload = map[string]interface{}{
"data": "helpers/payloads/command-injection.txt",
}
)
// Template is a YAML input file which defines the requests and
// others metadata for a scan template.
type Template struct { type Template struct {
// ID is the unique id for the template // description: |
// ID is the unique id for the template. IDs must be lowercase
// and must not contain spaces in it.
//
// #### Good IDs
//
// A good ID unqiuely identifies what the requests in the template
// are doing. Let's say you have a template that identifies a git-config
// file on the webservers, a good name would be `git-config-exposure`. Another
// example name is `azure-apps-nxdomain-takeover`.
// examples:
// - name: ID Example
// value: "\"cve-2021-19520\""
ID string `yaml:"id"` ID string `yaml:"id"`
// Info contains information about the template // description: |
// Info contains metadata information about the template. At minimum, it
// should contain `name`, `author`, `severity`, `description`, `tags`. Optionally
// you can also specify a list of `references` for the template.
Info map[string]interface{} `yaml:"info"` Info map[string]interface{} `yaml:"info"`
// RequestsHTTP contains the http request to make in the template // description: |
// Requests contains the http request to make in the template
RequestsHTTP []*http.Request `yaml:"requests,omitempty" json:"requests"` RequestsHTTP []*http.Request `yaml:"requests,omitempty" json:"requests"`
// RequestsDNS contains the dns request to make in the template // description: |
// DNS contains the dns request to make in the template
RequestsDNS []*dns.Request `yaml:"dns,omitempty" json:"dns"` RequestsDNS []*dns.Request `yaml:"dns,omitempty" json:"dns"`
// RequestsFile contains the file request to make in the template // description: |
// File contains the file request to make in the template
RequestsFile []*file.Request `yaml:"file,omitempty" json:"file"` RequestsFile []*file.Request `yaml:"file,omitempty" json:"file"`
// RequestsNetwork contains the network request to make in the template // description: |
// Network contains the network request to make in the template
RequestsNetwork []*network.Request `yaml:"network,omitempty" json:"network"` RequestsNetwork []*network.Request `yaml:"network,omitempty" json:"network"`
// RequestsHeadless contains the headless request to make in the template. // description: |
// Headless contains the headless request to make in the template.
RequestsHeadless []*headless.Request `yaml:"headless,omitempty" json:"headless"` RequestsHeadless []*headless.Request `yaml:"headless,omitempty" json:"headless"`
// Workflows is a yaml based workflow declaration code. // description: |
// Workflows is a yaml based workflow declaration code.
workflows.Workflow `yaml:",inline,omitempty"` workflows.Workflow `yaml:",inline,omitempty"`
CompiledWorkflow *workflows.Workflow `yaml:"-" json:"-" jsonschema:"-"` CompiledWorkflow *workflows.Workflow `yaml:"-" json:"-" jsonschema:"-"`

View File

@ -4,7 +4,8 @@ import "github.com/projectdiscovery/nuclei/v2/pkg/protocols"
// Workflow is a workflow to execute with chained requests, etc. // Workflow is a workflow to execute with chained requests, etc.
type Workflow struct { type Workflow struct {
// Workflows is a yaml based workflow declaration code. // description: |
// Workflows is a list of workflows to execute for a template.
Workflows []*WorkflowTemplate `yaml:"workflows,omitempty"` Workflows []*WorkflowTemplate `yaml:"workflows,omitempty"`
Options *protocols.ExecuterOptions Options *protocols.ExecuterOptions
@ -12,13 +13,22 @@ type Workflow struct {
// WorkflowTemplate is a template to be ran as part of a workflow // WorkflowTemplate is a template to be ran as part of a workflow
type WorkflowTemplate struct { type WorkflowTemplate struct {
// Template is the template to run // description: |
// Template is a single template or directory to execute as part of workflow.
// examples:
// - name: A single template
// value: "\"dns/worksites-detection.yaml\""
// - name: A template directory
// value: "\"misconfigurations/aem\""
Template string `yaml:"template"` Template string `yaml:"template"`
// Tags to perform filtering of supplied templates on // description: |
// Tags to run templates based on.
Tags string `yaml:"tags"` Tags string `yaml:"tags"`
// Matchers perform name based matching to run subtemplates for a workflow. // description: |
// Matchers perform name based matching to run subtemplates for a workflow.
Matchers []*Matcher `yaml:"matchers"` Matchers []*Matcher `yaml:"matchers"`
// Subtemplates are ran if the template matches. // description: |
// Subtemplates are ran if the `template` field Template matches.
Subtemplates []*WorkflowTemplate `yaml:"subtemplates"` Subtemplates []*WorkflowTemplate `yaml:"subtemplates"`
// Executers perform the actual execution for the workflow template // Executers perform the actual execution for the workflow template
Executers []*ProtocolExecuterPair Executers []*ProtocolExecuterPair
@ -32,8 +42,10 @@ type ProtocolExecuterPair struct {
// Matcher performs conditional matching on the workflow template results. // Matcher performs conditional matching on the workflow template results.
type Matcher struct { type Matcher struct {
// Name is the name of the item to match. // description: |
// Name is the name of the item to match.
Name string `yaml:"name"` Name string `yaml:"name"`
// Subtemplates are ran if the name of matcher matches. // description: |
// Subtemplates are ran if the name of matcher matches.
Subtemplates []*WorkflowTemplate `yaml:"subtemplates"` Subtemplates []*WorkflowTemplate `yaml:"subtemplates"`
} }