github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/templates/templates.go (about) 1 //go:generate dstdocgen -path "" -structure Template -output templates_doc.go -package templates 2 package templates 3 4 import ( 5 "encoding/json" 6 7 validate "github.com/go-playground/validator/v10" 8 "github.com/projectdiscovery/nuclei/v2/pkg/model" 9 "github.com/projectdiscovery/nuclei/v2/pkg/protocols" 10 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/variables" 11 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns" 12 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/file" 13 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/headless" 14 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/http" 15 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/network" 16 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/ssl" 17 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/websocket" 18 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/whois" 19 "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" 20 "github.com/projectdiscovery/nuclei/v2/pkg/workflows" 21 errorutil "github.com/projectdiscovery/utils/errors" 22 "go.uber.org/multierr" 23 "gopkg.in/yaml.v2" 24 ) 25 26 // Template is a YAML input file which defines all the requests and 27 // other metadata for a template. 28 type Template struct { 29 // description: | 30 // ID is the unique id for the template. 31 // 32 // #### Good IDs 33 // 34 // A good ID uniquely identifies what the requests in the template 35 // are doing. Let's say you have a template that identifies a git-config 36 // file on the webservers, a good name would be `git-config-exposure`. Another 37 // example name is `azure-apps-nxdomain-takeover`. 38 // examples: 39 // - name: ID Example 40 // value: "\"CVE-2021-19520\"" 41 ID string `yaml:"id" json:"id" jsonschema:"title=id of the template,description=The Unique ID for the template,example=cve-2021-19520,pattern=^([a-zA-Z0-9]+[-_])*[a-zA-Z0-9]+$"` 42 // description: | 43 // Info contains metadata information about the template. 44 // examples: 45 // - value: exampleInfoStructure 46 Info model.Info `yaml:"info" json:"info" jsonschema:"title=info for the template,description=Info contains metadata for the template"` 47 // description: | 48 // Requests contains the http request to make in the template. 49 // WARNING: 'requests' will be deprecated and will be removed in a future release. Please use 'http' instead. 50 // examples: 51 // - value: exampleNormalHTTPRequest 52 RequestsHTTP []*http.Request `yaml:"requests,omitempty" json:"requests,omitempty" jsonschema:"title=http requests to make,description=HTTP requests to make for the template"` 53 // description: | 54 // HTTP contains the http request to make in the template. 55 // examples: 56 // - value: exampleNormalHTTPRequest 57 // RequestsWithHTTP is placeholder(internal) only, and should not be used instead use RequestsHTTP 58 RequestsWithHTTP []*http.Request `yaml:"http,omitempty" json:"http,omitempty" jsonschema:"title=http requests to make,description=HTTP requests to make for the template"` 59 // description: | 60 // DNS contains the dns request to make in the template 61 // examples: 62 // - value: exampleNormalDNSRequest 63 RequestsDNS []*dns.Request `yaml:"dns,omitempty" json:"dns,omitempty" jsonschema:"title=dns requests to make,description=DNS requests to make for the template"` 64 // description: | 65 // File contains the file request to make in the template 66 // examples: 67 // - value: exampleNormalFileRequest 68 RequestsFile []*file.Request `yaml:"file,omitempty" json:"file,omitempty" jsonschema:"title=file requests to make,description=File requests to make for the template"` 69 // description: | 70 // Network contains the network request to make in the template 71 // WARNING: 'network' will be deprecated and will be removed in a future release. Please use 'tcp' instead. 72 // examples: 73 // - value: exampleNormalNetworkRequest 74 RequestsNetwork []*network.Request `yaml:"network,omitempty" json:"network,omitempty" jsonschema:"title=network requests to make,description=Network requests to make for the template"` 75 // description: | 76 // TCP contains the network request to make in the template 77 // examples: 78 // - value: exampleNormalNetworkRequest 79 // RequestsWithTCP is placeholder(internal) only, and should not be used instead use RequestsNetwork 80 RequestsWithTCP []*network.Request `yaml:"tcp,omitempty" json:"tcp,omitempty" jsonschema:"title=network(tcp) requests to make,description=Network requests to make for the template"` 81 // description: | 82 // Headless contains the headless request to make in the template. 83 RequestsHeadless []*headless.Request `yaml:"headless,omitempty" json:"headless,omitempty" jsonschema:"title=headless requests to make,description=Headless requests to make for the template"` 84 // description: | 85 // SSL contains the SSL request to make in the template. 86 RequestsSSL []*ssl.Request `yaml:"ssl,omitempty" json:"ssl,omitempty" jsonschema:"title=ssl requests to make,description=SSL requests to make for the template"` 87 // description: | 88 // Websocket contains the Websocket request to make in the template. 89 RequestsWebsocket []*websocket.Request `yaml:"websocket,omitempty" json:"websocket,omitempty" jsonschema:"title=websocket requests to make,description=Websocket requests to make for the template"` 90 91 // description: | 92 // WHOIS contains the WHOIS request to make in the template. 93 RequestsWHOIS []*whois.Request `yaml:"whois,omitempty" json:"whois,omitempty" jsonschema:"title=whois requests to make,description=WHOIS requests to make for the template"` 94 // description: | 95 // Workflows is a yaml based workflow declaration code. 96 workflows.Workflow `yaml:",inline,omitempty" jsonschema:"title=workflows to run,description=Workflows to run for the template"` 97 CompiledWorkflow *workflows.Workflow `yaml:"-" json:"-" jsonschema:"-"` 98 99 // description: | 100 // Self Contained marks Requests for the template as self-contained 101 SelfContained bool `yaml:"self-contained,omitempty" json:"self-contained,omitempty" jsonschema:"title=mark requests as self-contained,description=Mark Requests for the template as self-contained"` 102 // description: | 103 // Stop execution once first match is found 104 StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" json:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop at first match for the template"` 105 106 // description: | 107 // Signature is the request signature method 108 // values: 109 // - "AWS" 110 Signature http.SignatureTypeHolder `yaml:"signature,omitempty" json:"signature,omitempty" jsonschema:"title=signature is the http request signature method,description=Signature is the HTTP Request signature Method,enum=AWS"` 111 112 // description: | 113 // Variables contains any variables for the current request. 114 Variables variables.Variable `yaml:"variables,omitempty" json:"variables,omitempty" jsonschema:"title=variables for the http request,description=Variables contains any variables for the current request"` 115 116 // description: | 117 // Constants contains any scalar constant for the current template 118 Constants map[string]interface{} `yaml:"constants,omitempty" json:"constants,omitempty" jsonschema:"title=constant for the template,description=constants contains any constant for the template"` 119 120 // TotalRequests is the total number of requests for the template. 121 TotalRequests int `yaml:"-" json:"-"` 122 // Executer is the actual template executor for running template requests 123 Executer protocols.Executer `yaml:"-" json:"-"` 124 125 Path string `yaml:"-" json:"-"` 126 127 // Verified defines if the template signature is digitally verified 128 Verified bool `yaml:"-" json:"-"` 129 } 130 131 // TemplateProtocols is a list of accepted template protocols 132 var TemplateProtocols = []string{ 133 "dns", 134 "file", 135 "http", 136 "headless", 137 "network", 138 "workflow", 139 "ssl", 140 "websocket", 141 "whois", 142 } 143 144 // Type returns the type of the template 145 func (template *Template) Type() types.ProtocolType { 146 switch { 147 case len(template.RequestsDNS) > 0: 148 return types.DNSProtocol 149 case len(template.RequestsFile) > 0: 150 return types.FileProtocol 151 case len(template.RequestsHTTP) > 0: 152 return types.HTTPProtocol 153 case len(template.RequestsHeadless) > 0: 154 return types.HeadlessProtocol 155 case len(template.RequestsNetwork) > 0: 156 return types.NetworkProtocol 157 case len(template.Workflow.Workflows) > 0: 158 return types.WorkflowProtocol 159 case len(template.RequestsSSL) > 0: 160 return types.SSLProtocol 161 case len(template.RequestsWebsocket) > 0: 162 return types.WebsocketProtocol 163 case len(template.RequestsWHOIS) > 0: 164 return types.WHOISProtocol 165 default: 166 return types.InvalidProtocol 167 } 168 } 169 170 // MarshalYAML forces recursive struct validation during marshal operation 171 func (template *Template) MarshalYAML() ([]byte, error) { 172 out, marshalErr := yaml.Marshal(template) 173 errValidate := validate.New().Struct(template) 174 return out, multierr.Append(marshalErr, errValidate) 175 } 176 177 // MarshalYAML forces recursive struct validation after unmarshal operation 178 func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error { 179 type Alias Template 180 alias := &Alias{} 181 err := unmarshal(alias) 182 if err != nil { 183 return err 184 } 185 *template = Template(*alias) 186 187 if len(template.RequestsHTTP) > 0 || len(template.RequestsNetwork) > 0 { 188 _ = deprecatedProtocolNameTemplates.Set(template.ID, true) 189 } 190 191 if len(alias.RequestsHTTP) > 0 && len(alias.RequestsWithHTTP) > 0 { 192 return errorutil.New("use http or requests, both are not supported").WithTag("invalid template") 193 } 194 if len(alias.RequestsNetwork) > 0 && len(alias.RequestsWithTCP) > 0 { 195 return errorutil.New("use tcp or network, both are not supported").WithTag("invalid template") 196 } 197 if len(alias.RequestsWithHTTP) > 0 { 198 template.RequestsHTTP = alias.RequestsWithHTTP 199 } 200 if len(alias.RequestsWithTCP) > 0 { 201 template.RequestsNetwork = alias.RequestsWithTCP 202 } 203 return validate.New().Struct(template) 204 } 205 206 // MarshalJSON forces recursive struct validation during marshal operation 207 func (template *Template) MarshalJSON() ([]byte, error) { 208 out, marshalErr := json.Marshal(template) 209 errValidate := validate.New().Struct(template) 210 return out, multierr.Append(marshalErr, errValidate) 211 } 212 213 // UnmarshalJSON forces recursive struct validation after unmarshal operation 214 func (template *Template) UnmarshalJSON(data []byte) error { 215 type Alias Template 216 alias := &Alias{} 217 err := json.Unmarshal(data, alias) 218 if err != nil { 219 return err 220 } 221 *template = Template(*alias) 222 return validate.New().Struct(template) 223 }