diff --git a/SYNTAX-REFERENCE.md b/SYNTAX-REFERENCE.md
index 8ea798291..ed19bd9c0 100755
--- a/SYNTAX-REFERENCE.md
+++ b/SYNTAX-REFERENCE.md
@@ -880,7 +880,7 @@ Valid values:
-method string
+method HTTPMethodTypeHolder
diff --git a/nuclei-jsonschema.json b/nuclei-jsonschema.json
index da66f3e9b..1d179d68a 100755
--- a/nuclei-jsonschema.json
+++ b/nuclei-jsonschema.json
@@ -576,6 +576,23 @@
"additionalProperties": false,
"type": "object"
},
+ "http.HTTPMethodTypeHolder": {
+ "enum": [
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "CONNECT",
+ "OPTIONS",
+ "TRACE",
+ "PATCH",
+ "PURGE"
+ ],
+ "type": "string",
+ "title": "method is the http request method",
+ "description": "Method is the HTTP Request Method,enum=GET,enum=HEAD,enum=POST,enum=PUT,enum=DELETE,enum=CONNECT,enum=OPTIONS,enum=TRACE,enum=PATCH,enum=PURGE"
+ },
"http.Request": {
"properties": {
"matchers": {
@@ -637,19 +654,8 @@
"description": "Attack is the type of payload combinations to perform"
},
"method": {
- "enum": [
- "GET",
- "HEAD",
- "POST",
- "PUT",
- "DELETE",
- "CONNECT",
- "OPTIONS",
- "TRACE",
- "PATCH",
- "PURGE"
- ],
- "type": "string",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "$ref": "#/definitions/http.HTTPMethodTypeHolder",
"title": "method is the http request method",
"description": "Method is the HTTP Request Method"
},
diff --git a/v2/pkg/protocols/http/build_request.go b/v2/pkg/protocols/http/build_request.go
index 6b9b01f18..8c8a2dbc8 100644
--- a/v2/pkg/protocols/http/build_request.go
+++ b/v2/pkg/protocols/http/build_request.go
@@ -191,7 +191,7 @@ func (r *requestGenerator) makeHTTPRequestFromModel(ctx context.Context, data st
return nil, errors.Wrap(err, "could not evaluate helper expressions")
}
- method, err := expressions.Evaluate(r.request.Method, finalValues)
+ method, err := expressions.Evaluate(r.request.Method.String(), finalValues)
if err != nil {
return nil, errors.Wrap(err, "could not evaluate helper expressions")
}
diff --git a/v2/pkg/protocols/http/build_request_test.go b/v2/pkg/protocols/http/build_request_test.go
index 429676a37..a77e3c947 100644
--- a/v2/pkg/protocols/http/build_request_test.go
+++ b/v2/pkg/protocols/http/build_request_test.go
@@ -71,7 +71,7 @@ func TestMakeRequestFromModal(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}/login.php"},
- Method: "POST",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPPost},
Body: "username=test&password=pass",
Headers: map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
@@ -103,7 +103,7 @@ func TestMakeRequestFromModalTrimSuffixSlash(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}?query=example"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
}
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
ID: templateID,
@@ -211,7 +211,7 @@ func TestMakeRequestFromModelUniqueInteractsh(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}/?u=http://{{interactsh-url}}/&href=http://{{interactsh-url}}/&action=http://{{interactsh-url}}/&host={{interactsh-url}}"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
}
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
ID: templateID,
diff --git a/v2/pkg/protocols/http/cluster_test.go b/v2/pkg/protocols/http/cluster_test.go
index 136b3feb9..a16db41ee 100644
--- a/v2/pkg/protocols/http/cluster_test.go
+++ b/v2/pkg/protocols/http/cluster_test.go
@@ -10,6 +10,6 @@ func TestCanCluster(t *testing.T) {
req := &Request{Unsafe: true}
require.False(t, req.CanCluster(&Request{}), "could cluster unsafe request")
- req = &Request{Path: []string{"{{BaseURL}}"}, Method: "GET"}
- require.True(t, req.CanCluster(&Request{Path: []string{"{{BaseURL}}"}, Method: "GET"}), "could not cluster GET request")
+ req = &Request{Path: []string{"{{BaseURL}}"}, Method: HTTPMethodTypeHolder{MethodType: HTTPGet}}
+ require.True(t, req.CanCluster(&Request{Path: []string{"{{BaseURL}}"}, Method: HTTPMethodTypeHolder{MethodType: HTTPGet}}), "could not cluster GET request")
}
diff --git a/v2/pkg/protocols/http/http.go b/v2/pkg/protocols/http/http.go
index f85e49c2c..3fbe3a8ec 100644
--- a/v2/pkg/protocols/http/http.go
+++ b/v2/pkg/protocols/http/http.go
@@ -66,7 +66,7 @@ type Request struct {
// - "TRACE"
// - "PATCH"
// - "PURGE"
- Method string `yaml:"method,omitempty" jsonschema:"title=method is the http request method,description=Method is the HTTP Request Method,enum=GET,enum=HEAD,enum=POST,enum=PUT,enum=DELETE,enum=CONNECT,enum=OPTIONS,enum=TRACE,enum=PATCH,enum=PURGE"`
+ Method HTTPMethodTypeHolder `yaml:"method,omitempty" jsonschema:"title=method is the http request method,description=Method is the HTTP Request Method,enum=GET,enum=HEAD,enum=POST,enum=PUT,enum=DELETE,enum=CONNECT,enum=OPTIONS,enum=TRACE,enum=PATCH,enum=PURGE"`
// description: |
// Body is an optional parameter which contains HTTP Request body.
// examples:
@@ -242,7 +242,7 @@ func (request *Request) Compile(options *protocols.ExecuterOptions) error {
var hasPayloadName bool
// search for markers in all request parts
var inputs []string
- inputs = append(inputs, request.Method, request.Body)
+ inputs = append(inputs, request.Method.String(), request.Body)
inputs = append(inputs, request.Raw...)
for k, v := range request.customHeaders {
inputs = append(inputs, fmt.Sprintf("%s: %s", k, v))
diff --git a/v2/pkg/protocols/http/http_method_types.go b/v2/pkg/protocols/http/http_method_types.go
new file mode 100644
index 000000000..987dde979
--- /dev/null
+++ b/v2/pkg/protocols/http/http_method_types.go
@@ -0,0 +1,112 @@
+package http
+
+import (
+ "encoding/json"
+ "errors"
+ "strings"
+
+ "github.com/alecthomas/jsonschema"
+)
+
+// HTTPMethodType is the type of the method specified
+type HTTPMethodType int
+
+const (
+ HTTPGet HTTPMethodType = iota + 1
+ HTTPHead
+ HTTPPost
+ HTTPPut
+ HTTPDelete
+ HTTPConnect
+ HTTPOptions
+ HTTPTrace
+ HTTPPatch
+ HTTPPurge
+ //limit
+ limit
+)
+
+// HTTPMethodMapping is a table for conversion of method from string.
+var HTTPMethodMapping = map[HTTPMethodType]string{
+ HTTPGet: "GET",
+ HTTPHead: "HEAD",
+ HTTPPost: "POST",
+ HTTPPut: "PUT",
+ HTTPDelete: "DELETE",
+ HTTPConnect: "CONNECT",
+ HTTPOptions: "OPTIONS",
+ HTTPTrace: "TRACE",
+ HTTPPatch: "PATCH",
+ HTTPPurge: "PURGE",
+}
+
+// GetSupportedHTTPMethodTypes returns list of supported types
+func GetSupportedHTTPMethodTypes() []HTTPMethodType {
+ var result []HTTPMethodType
+ for index := HTTPMethodType(1); index < limit; index++ {
+ result = append(result, index)
+ }
+ return result
+}
+
+func toHTTPMethodTypes(valueToMap string) (HTTPMethodType, error) {
+ normalizedValue := normalizeValue(valueToMap)
+ for key, currentValue := range HTTPMethodMapping {
+ if normalizedValue == currentValue {
+ return key, nil
+ }
+ }
+ return -1, errors.New("Invalid HTTP method verb: " + valueToMap)
+}
+
+func normalizeValue(value string) string {
+ return strings.TrimSpace(strings.ToUpper(value))
+}
+
+func (t HTTPMethodType) String() string {
+ return HTTPMethodMapping[t]
+}
+
+// HTTPMethodTypeHolder is used to hold internal type of the HTTP Method
+type HTTPMethodTypeHolder struct {
+ MethodType HTTPMethodType
+}
+
+func (holder HTTPMethodTypeHolder) String() string {
+ return holder.MethodType.String()
+}
+
+func (holder HTTPMethodTypeHolder) JSONSchemaType() *jsonschema.Type {
+ gotType := &jsonschema.Type{
+ Type: "string",
+ Title: "method is the HTTP request method",
+ Description: "Method is the HTTP Request Method,enum=GET,enum=HEAD,enum=POST,enum=PUT,enum=DELETE,enum=CONNECT,enum=OPTIONS,enum=TRACE,enum=PATCH,enum=PURGE",
+ }
+ for _, types := range GetSupportedHTTPMethodTypes() {
+ gotType.Enum = append(gotType.Enum, types.String())
+ }
+ return gotType
+}
+
+func (holder *HTTPMethodTypeHolder) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var marshalledTypes string
+ if err := unmarshal(&marshalledTypes); err != nil {
+ return err
+ }
+
+ computedType, err := toHTTPMethodTypes(marshalledTypes)
+ if err != nil {
+ return err
+ }
+
+ holder.MethodType = computedType
+ return nil
+}
+
+func (holder *HTTPMethodTypeHolder) MarshalJSON() ([]byte, error) {
+ return json.Marshal(holder.MethodType.String())
+}
+
+func (holder HTTPMethodTypeHolder) MarshalYAML() (interface{}, error) {
+ return holder.MethodType.String(), nil
+}
diff --git a/v2/pkg/protocols/http/operators_test.go b/v2/pkg/protocols/http/operators_test.go
index bc7b888a2..7950bc64f 100644
--- a/v2/pkg/protocols/http/operators_test.go
+++ b/v2/pkg/protocols/http/operators_test.go
@@ -25,7 +25,7 @@ func TestResponseToDSLMap(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}?test=1"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
}
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
ID: templateID,
@@ -55,7 +55,7 @@ func TestHTTPOperatorMatch(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}?test=1"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
}
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
ID: templateID,
@@ -143,7 +143,7 @@ func TestHTTPOperatorExtract(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}?test=1"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
}
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
ID: templateID,
@@ -257,7 +257,7 @@ func TestHTTPMakeResult(t *testing.T) {
ID: templateID,
Name: "testing",
Path: []string{"{{BaseURL}}?test=1"},
- Method: "GET",
+ Method: HTTPMethodTypeHolder{MethodType: HTTPGet},
Operators: operators.Operators{
Matchers: []*matchers.Matcher{{
Name: "test",
diff --git a/v2/pkg/templates/templates_doc.go b/v2/pkg/templates/templates_doc.go
index c7f1b016b..52c5da75a 100644
--- a/v2/pkg/templates/templates_doc.go
+++ b/v2/pkg/templates/templates_doc.go
@@ -344,7 +344,7 @@ func init() {
"clusterbomb",
}
HTTPRequestDoc.Fields[8].Name = "method"
- HTTPRequestDoc.Fields[8].Type = "string"
+ HTTPRequestDoc.Fields[8].Type = "HTTPMethodTypeHolder"
HTTPRequestDoc.Fields[8].Note = ""
HTTPRequestDoc.Fields[8].Description = "Method is the HTTP Request Method."
HTTPRequestDoc.Fields[8].Comments[encoder.LineComment] = "Method is the HTTP Request Method."
diff --git a/v2/pkg/templates/templates_doc_examples.go b/v2/pkg/templates/templates_doc_examples.go
index e6655c6d9..88d5e5e88 100644
--- a/v2/pkg/templates/templates_doc_examples.go
+++ b/v2/pkg/templates/templates_doc_examples.go
@@ -24,7 +24,7 @@ var (
Tags: stringslice.StringSlice{Value: "cve,cve2021,rce,ruby"},
}
exampleNormalHTTPRequest = &http.Request{
- Method: "GET",
+ Method: http.HTTPMethodTypeHolder{MethodType: http.HTTPGet},
Path: []string{"{{BaseURL}}/.git/config"},
Operators: operators.Operators{
MatchersCondition: "and",