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  }