diff --git a/v2/pkg/templates/templates_doc.go b/v2/pkg/templates/templates_doc.go
index d101c63b6..c5c77200b 100644
--- a/v2/pkg/templates/templates_doc.go
+++ b/v2/pkg/templates/templates_doc.go
@@ -16,14 +16,20 @@ var (
MODELClassificationDoc encoder.Doc
HTTPRequestDoc encoder.Doc
MATCHERSMatcherDoc encoder.Doc
+ MatcherTypeHolderDoc encoder.Doc
EXTRACTORSExtractorDoc encoder.Doc
+ ExtractorTypeHolderDoc encoder.Doc
GENERATORSAttackTypeHolderDoc encoder.Doc
+ HTTPMethodTypeHolderDoc encoder.Doc
DNSRequestDoc encoder.Doc
+ DNSRequestTypeHolderDoc encoder.Doc
FILERequestDoc encoder.Doc
NETWORKRequestDoc encoder.Doc
NETWORKInputDoc encoder.Doc
+ NetworkInputTypeHolderDoc encoder.Doc
HEADLESSRequestDoc encoder.Doc
ENGINEActionDoc encoder.Doc
+ ActionTypeHolderDoc encoder.Doc
SSLRequestDoc encoder.Doc
WEBSOCKETRequestDoc encoder.Doc
WEBSOCKETInputDoc encoder.Doc
@@ -235,7 +241,20 @@ func init() {
FieldName: "severity",
},
}
- SEVERITYHolderDoc.Fields = make([]encoder.Doc, 0)
+ SEVERITYHolderDoc.Fields = make([]encoder.Doc, 1)
+ SEVERITYHolderDoc.Fields[0].Name = ""
+ SEVERITYHolderDoc.Fields[0].Type = "Severity"
+ SEVERITYHolderDoc.Fields[0].Note = ""
+ SEVERITYHolderDoc.Fields[0].Description = ""
+ SEVERITYHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ SEVERITYHolderDoc.Fields[0].EnumFields = []string{
+ "undefined",
+ "info",
+ "low",
+ "medium",
+ "high",
+ "critical",
+ }
MODELClassificationDoc.Type = "model.Classification"
MODELClassificationDoc.Comments[encoder.LineComment] = ""
@@ -287,6 +306,72 @@ func init() {
FieldName: "requests",
},
}
+ HTTPRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "template-id",
+ Value: "ID of the template executed",
+ },
+ {
+ Key: "template-info",
+ Value: "Info Block of the template executed",
+ },
+ {
+ Key: "template-path",
+ Value: "Path of the template executed",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "request",
+ Value: "HTTP request made from the client",
+ },
+ {
+ Key: "response",
+ Value: "HTTP response recieved from server",
+ },
+ {
+ Key: "status_code",
+ Value: "Status Code received from the Server",
+ },
+ {
+ Key: "body",
+ Value: "HTTP response body received from server (default)",
+ },
+ {
+ Key: "content_length",
+ Value: "HTTP Response content length",
+ },
+ {
+ Key: "header,all_headers",
+ Value: "HTTP response headers",
+ },
+ {
+ Key: "duration",
+ Value: "HTTP request time duration",
+ },
+ {
+ Key: "all",
+ Value: "HTTP response body + headers",
+ },
+ {
+ Key: "cookies_from_response",
+ Value: "HTTP response cookies in name:value format",
+ },
+ {
+ Key: "headers_from_response",
+ Value: "HTTP response headers in name:value format",
+ },
+ }
HTTPRequestDoc.Fields = make([]encoder.Doc, 27)
HTTPRequestDoc.Fields[0].Name = "matchers"
HTTPRequestDoc.Fields[0].Type = "[]matchers.Matcher"
@@ -590,6 +675,30 @@ func init() {
"true",
}
+ MatcherTypeHolderDoc.Type = "MatcherTypeHolder"
+ MatcherTypeHolderDoc.Comments[encoder.LineComment] = " MatcherTypeHolder is used to hold internal type of the matcher"
+ MatcherTypeHolderDoc.Description = "MatcherTypeHolder is used to hold internal type of the matcher"
+ MatcherTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "matchers.Matcher",
+ FieldName: "type",
+ },
+ }
+ MatcherTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ MatcherTypeHolderDoc.Fields[0].Name = ""
+ MatcherTypeHolderDoc.Fields[0].Type = "MatcherType"
+ MatcherTypeHolderDoc.Fields[0].Note = ""
+ MatcherTypeHolderDoc.Fields[0].Description = ""
+ MatcherTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ MatcherTypeHolderDoc.Fields[0].EnumFields = []string{
+ "word",
+ "regex",
+ "binary",
+ "status",
+ "size",
+ "dsl",
+ }
+
EXTRACTORSExtractorDoc.Type = "extractors.Extractor"
EXTRACTORSExtractorDoc.Comments[encoder.LineComment] = " Extractor is used to extract part of response using a regex."
EXTRACTORSExtractorDoc.Description = "Extractor is used to extract part of response using a regex."
@@ -704,6 +813,28 @@ func init() {
"true",
}
+ ExtractorTypeHolderDoc.Type = "ExtractorTypeHolder"
+ ExtractorTypeHolderDoc.Comments[encoder.LineComment] = " ExtractorTypeHolder is used to hold internal type of the extractor"
+ ExtractorTypeHolderDoc.Description = "ExtractorTypeHolder is used to hold internal type of the extractor"
+ ExtractorTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "extractors.Extractor",
+ FieldName: "type",
+ },
+ }
+ ExtractorTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ ExtractorTypeHolderDoc.Fields[0].Name = ""
+ ExtractorTypeHolderDoc.Fields[0].Type = "ExtractorType"
+ ExtractorTypeHolderDoc.Fields[0].Note = ""
+ ExtractorTypeHolderDoc.Fields[0].Description = ""
+ ExtractorTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ ExtractorTypeHolderDoc.Fields[0].EnumFields = []string{
+ "regex",
+ "kval",
+ "xpath",
+ "json",
+ }
+
GENERATORSAttackTypeHolderDoc.Type = "generators.AttackTypeHolder"
GENERATORSAttackTypeHolderDoc.Comments[encoder.LineComment] = " AttackTypeHolder is used to hold internal type of the protocol"
GENERATORSAttackTypeHolderDoc.Description = "AttackTypeHolder is used to hold internal type of the protocol"
@@ -721,7 +852,45 @@ func init() {
FieldName: "attack",
},
}
- GENERATORSAttackTypeHolderDoc.Fields = make([]encoder.Doc, 0)
+ GENERATORSAttackTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ GENERATORSAttackTypeHolderDoc.Fields[0].Name = ""
+ GENERATORSAttackTypeHolderDoc.Fields[0].Type = "AttackType"
+ GENERATORSAttackTypeHolderDoc.Fields[0].Note = ""
+ GENERATORSAttackTypeHolderDoc.Fields[0].Description = ""
+ GENERATORSAttackTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ GENERATORSAttackTypeHolderDoc.Fields[0].EnumFields = []string{
+ "batteringram",
+ "pitchfork",
+ "clusterbomb",
+ }
+
+ HTTPMethodTypeHolderDoc.Type = "HTTPMethodTypeHolder"
+ HTTPMethodTypeHolderDoc.Comments[encoder.LineComment] = " HTTPMethodTypeHolder is used to hold internal type of the HTTP Method"
+ HTTPMethodTypeHolderDoc.Description = "HTTPMethodTypeHolder is used to hold internal type of the HTTP Method"
+ HTTPMethodTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "http.Request",
+ FieldName: "method",
+ },
+ }
+ HTTPMethodTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ HTTPMethodTypeHolderDoc.Fields[0].Name = ""
+ HTTPMethodTypeHolderDoc.Fields[0].Type = "HTTPMethodType"
+ HTTPMethodTypeHolderDoc.Fields[0].Note = ""
+ HTTPMethodTypeHolderDoc.Fields[0].Description = ""
+ HTTPMethodTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ HTTPMethodTypeHolderDoc.Fields[0].EnumFields = []string{
+ "GET",
+ "GET",
+ "POST",
+ "PUT",
+ "DELETE",
+ "CONNECT",
+ "OPTIONS",
+ "TRACE",
+ "PATCH",
+ "PURGE",
+ }
DNSRequestDoc.Type = "dns.Request"
DNSRequestDoc.Comments[encoder.LineComment] = " Request contains a DNS protocol request to be made from a template"
@@ -734,6 +903,64 @@ func init() {
FieldName: "dns",
},
}
+ DNSRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "template-id",
+ Value: "ID of the template executed",
+ },
+ {
+ Key: "template-info",
+ Value: "Info Block of the template executed",
+ },
+ {
+ Key: "template-path",
+ Value: "Path of the template executed",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ {
+ Key: "request",
+ Value: "Request contains the DNS request in text format",
+ },
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "rcode",
+ Value: "Rcode field returned for the DNS request",
+ },
+ {
+ Key: "question",
+ Value: "Question contains the DNS question field",
+ },
+ {
+ Key: "extra",
+ Value: "Extra contains the DNS response extra field",
+ },
+ {
+ Key: "answer",
+ Value: "Answer contains the DNS response answer field",
+ },
+ {
+ Key: "ns",
+ Value: "NS contains the DNS response NS field",
+ },
+ {
+ Key: "raw,body,all",
+ Value: "Raw contains the raw DNS response (default)",
+ },
+ {
+ Key: "trace",
+ Value: "Trace contains trace data for DNS request if enabled",
+ },
+ }
DNSRequestDoc.Fields = make([]encoder.Doc, 12)
DNSRequestDoc.Fields[0].Name = "matchers"
DNSRequestDoc.Fields[0].Type = "[]matchers.Matcher"
@@ -814,6 +1041,33 @@ func init() {
DNSRequestDoc.Fields[11].Description = "Resolvers to use for the dns requests"
DNSRequestDoc.Fields[11].Comments[encoder.LineComment] = " Resolvers to use for the dns requests"
+ DNSRequestTypeHolderDoc.Type = "DNSRequestTypeHolder"
+ DNSRequestTypeHolderDoc.Comments[encoder.LineComment] = " DNSRequestTypeHolder is used to hold internal type of the DNS type"
+ DNSRequestTypeHolderDoc.Description = "DNSRequestTypeHolder is used to hold internal type of the DNS type"
+ DNSRequestTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "dns.Request",
+ FieldName: "type",
+ },
+ }
+ DNSRequestTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ DNSRequestTypeHolderDoc.Fields[0].Name = ""
+ DNSRequestTypeHolderDoc.Fields[0].Type = "DNSRequestType"
+ DNSRequestTypeHolderDoc.Fields[0].Note = ""
+ DNSRequestTypeHolderDoc.Fields[0].Description = ""
+ DNSRequestTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ DNSRequestTypeHolderDoc.Fields[0].EnumFields = []string{
+ "A",
+ "NS",
+ "DS",
+ "CNAME",
+ "SOA",
+ "PTR",
+ "MX",
+ "TXT",
+ "AAAA",
+ }
+
FILERequestDoc.Type = "file.Request"
FILERequestDoc.Comments[encoder.LineComment] = " Request contains a File matching mechanism for local disk operations."
FILERequestDoc.Description = "Request contains a File matching mechanism for local disk operations."
@@ -825,6 +1079,36 @@ func init() {
FieldName: "file",
},
}
+ FILERequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "template-id",
+ Value: "ID of the template executed",
+ },
+ {
+ Key: "template-info",
+ Value: "Info Block of the template executed",
+ },
+ {
+ Key: "template-path",
+ Value: "Path of the template executed",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ {
+ Key: "path",
+ Value: "Path is the path of file on local filesystem",
+ },
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "raw,body,all,data",
+ Value: "Raw contains the raw file contents",
+ },
+ }
FILERequestDoc.Fields = make([]encoder.Doc, 8)
FILERequestDoc.Fields[0].Name = "matchers"
FILERequestDoc.Fields[0].Type = "[]matchers.Matcher"
@@ -888,6 +1172,44 @@ func init() {
FieldName: "network",
},
}
+ NETWORKRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "template-id",
+ Value: "ID of the template executed",
+ },
+ {
+ Key: "template-info",
+ Value: "Info Block of the template executed",
+ },
+ {
+ Key: "template-path",
+ Value: "Path of the template executed",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "request",
+ Value: "Network request made from the client",
+ },
+ {
+ Key: "body,all,data",
+ Value: "Network response recieved from server (default)",
+ },
+ {
+ Key: "raw",
+ Value: "Full Network protocol data",
+ },
+ }
NETWORKRequestDoc.Fields = make([]encoder.Doc, 10)
NETWORKRequestDoc.Fields[0].Name = "id"
NETWORKRequestDoc.Fields[0].Type = "string"
@@ -993,6 +1315,26 @@ func init() {
NETWORKInputDoc.Fields[3].AddExample("", "prefix")
+ NetworkInputTypeHolderDoc.Type = "NetworkInputTypeHolder"
+ NetworkInputTypeHolderDoc.Comments[encoder.LineComment] = " NetworkInputTypeHolder is used to hold internal type of the Network type"
+ NetworkInputTypeHolderDoc.Description = "NetworkInputTypeHolder is used to hold internal type of the Network type"
+ NetworkInputTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "network.Input",
+ FieldName: "type",
+ },
+ }
+ NetworkInputTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ NetworkInputTypeHolderDoc.Fields[0].Name = ""
+ NetworkInputTypeHolderDoc.Fields[0].Type = "NetworkInputType"
+ NetworkInputTypeHolderDoc.Fields[0].Note = ""
+ NetworkInputTypeHolderDoc.Fields[0].Description = ""
+ NetworkInputTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ NetworkInputTypeHolderDoc.Fields[0].EnumFields = []string{
+ "hex",
+ "text",
+ }
+
HEADLESSRequestDoc.Type = "headless.Request"
HEADLESSRequestDoc.Comments[encoder.LineComment] = " Request contains a Headless protocol request to be made from a template"
HEADLESSRequestDoc.Description = "Request contains a Headless protocol request to be made from a template"
@@ -1002,6 +1344,40 @@ func init() {
FieldName: "headless",
},
}
+ HEADLESSRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "template-id",
+ Value: "ID of the template executed",
+ },
+ {
+ Key: "template-info",
+ Value: "Info Block of the template executed",
+ },
+ {
+ Key: "template-path",
+ Value: "Path of the template executed",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "req",
+ Value: "Headless request made from the client",
+ },
+ {
+ Key: "resp,body,data",
+ Value: "Headless response recieved from client (default)",
+ },
+ }
HEADLESSRequestDoc.Fields = make([]encoder.Doc, 5)
HEADLESSRequestDoc.Fields[0].Name = "id"
HEADLESSRequestDoc.Fields[0].Type = "string"
@@ -1064,6 +1440,46 @@ func init() {
ENGINEActionDoc.Fields[3].Description = "Action is the type of the action to perform."
ENGINEActionDoc.Fields[3].Comments[encoder.LineComment] = "Action is the type of the action to perform."
+ ActionTypeHolderDoc.Type = "ActionTypeHolder"
+ ActionTypeHolderDoc.Comments[encoder.LineComment] = " ActionTypeHolder is used to hold internal type of the action"
+ ActionTypeHolderDoc.Description = "ActionTypeHolder is used to hold internal type of the action"
+ ActionTypeHolderDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "engine.Action",
+ FieldName: "action",
+ },
+ }
+ ActionTypeHolderDoc.Fields = make([]encoder.Doc, 1)
+ ActionTypeHolderDoc.Fields[0].Name = ""
+ ActionTypeHolderDoc.Fields[0].Type = "ActionType"
+ ActionTypeHolderDoc.Fields[0].Note = ""
+ ActionTypeHolderDoc.Fields[0].Description = ""
+ ActionTypeHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
+ ActionTypeHolderDoc.Fields[0].EnumFields = []string{
+ "navigate",
+ "script",
+ "click",
+ "rightclick",
+ "text",
+ "screenshot",
+ "time",
+ "select",
+ "files",
+ "waitload",
+ "getresource",
+ "extract",
+ "setmethod",
+ "addheader",
+ "setheader",
+ "deleteheader",
+ "setbody",
+ "waitevent",
+ "keyboard",
+ "debug",
+ "sleep",
+ "waitvisible",
+ }
+
SSLRequestDoc.Type = "ssl.Request"
SSLRequestDoc.Comments[encoder.LineComment] = " Request is a request for the SSL protocol"
SSLRequestDoc.Description = "Request is a request for the SSL protocol"
@@ -1073,6 +1489,28 @@ func init() {
FieldName: "ssl",
},
}
+ SSLRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "response",
+ Value: "JSON SSL protocol handshake details",
+ },
+ {
+ Key: "not_after",
+ Value: "Timestamp after which the remote cert expires",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ }
SSLRequestDoc.Fields = make([]encoder.Doc, 4)
SSLRequestDoc.Fields[0].Name = "matchers"
SSLRequestDoc.Fields[0].Type = "[]matchers.Matcher"
@@ -1108,6 +1546,32 @@ func init() {
FieldName: "websocket",
},
}
+ WEBSOCKETRequestDoc.PartDefinitions = []encoder.KeyValue{
+ {
+ Key: "type",
+ Value: "Type is the type of request made",
+ },
+ {
+ Key: "success",
+ Value: "Success specifies whether websocket connection was successful",
+ },
+ {
+ Key: "request",
+ Value: "Websocket request made to the server",
+ },
+ {
+ Key: "response",
+ Value: "Websocket response recieved from the server",
+ },
+ {
+ Key: "host",
+ Value: "Host is the input to the template",
+ },
+ {
+ Key: "matched",
+ Value: "Matched is the input which was matched upon",
+ },
+ }
WEBSOCKETRequestDoc.Fields = make([]encoder.Doc, 8)
WEBSOCKETRequestDoc.Fields[0].Name = "matchers"
WEBSOCKETRequestDoc.Fields[0].Type = "[]matchers.Matcher"
@@ -1259,14 +1723,20 @@ func GetTemplateDoc() *encoder.FileDoc {
&MODELClassificationDoc,
&HTTPRequestDoc,
&MATCHERSMatcherDoc,
+ &MatcherTypeHolderDoc,
&EXTRACTORSExtractorDoc,
+ &ExtractorTypeHolderDoc,
&GENERATORSAttackTypeHolderDoc,
+ &HTTPMethodTypeHolderDoc,
&DNSRequestDoc,
+ &DNSRequestTypeHolderDoc,
&FILERequestDoc,
&NETWORKRequestDoc,
&NETWORKInputDoc,
+ &NetworkInputTypeHolderDoc,
&HEADLESSRequestDoc,
&ENGINEActionDoc,
+ &ActionTypeHolderDoc,
&SSLRequestDoc,
&WEBSOCKETRequestDoc,
&WEBSOCKETInputDoc,
From 0ca39bb6d2b8e8aa275644a6431813f5f079b937 Mon Sep 17 00:00:00 2001
From: GitHub Action
Date: Fri, 3 Dec 2021 03:46:08 +0000
Subject: [PATCH 12/16] Auto Generate Syntax Docs + JSONSchema [Fri Dec 3
03:46:08 UTC 2021] :robot:
---
SYNTAX-REFERENCE.md | 6 +++---
v2/pkg/templates/templates_doc.go | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/SYNTAX-REFERENCE.md b/SYNTAX-REFERENCE.md
index aed620891..ab5ea9ae9 100755
--- a/SYNTAX-REFERENCE.md
+++ b/SYNTAX-REFERENCE.md
@@ -136,7 +136,7 @@ dns:
type: CNAME
class: inet
retries: 2
- recursion: true
+ recursion: false
```
@@ -2146,7 +2146,7 @@ name: '{{FQDN}}'
type: CNAME
class: inet
retries: 2
-recursion: true
+recursion: false
```
Part Definitions:
@@ -2365,7 +2365,7 @@ trace-max-recursion: 100
-recursion bool
+recursion dns.bool
diff --git a/v2/pkg/templates/templates_doc.go b/v2/pkg/templates/templates_doc.go
index c5c77200b..e1b739e9f 100644
--- a/v2/pkg/templates/templates_doc.go
+++ b/v2/pkg/templates/templates_doc.go
@@ -1031,7 +1031,7 @@ func init() {
DNSRequestDoc.Fields[9].AddExample("Use a retry of 100 to 150 generally", 100)
DNSRequestDoc.Fields[10].Name = "recursion"
- DNSRequestDoc.Fields[10].Type = "bool"
+ DNSRequestDoc.Fields[10].Type = "dns.bool"
DNSRequestDoc.Fields[10].Note = ""
DNSRequestDoc.Fields[10].Description = "Recursion determines if resolver should recurse all records to get fresh results."
DNSRequestDoc.Fields[10].Comments[encoder.LineComment] = "Recursion determines if resolver should recurse all records to get fresh results."
From 83364211790eefc5d205d9c894d4770510310848 Mon Sep 17 00:00:00 2001
From: Mzack9999
Date: Sat, 4 Dec 2021 18:40:11 +0100
Subject: [PATCH 13/16] Improving headless test cases (#1313)
* Adding headless test cases
---
.../headless/headless-basic.yaml | 18 +++++
.../headless/headless-extract-values.yaml | 31 +++++++
.../headless/headless-header-action.yaml | 24 ++++++
v2/cmd/integration-test/headless.go | 81 +++++++++++++++++++
v2/cmd/integration-test/integration-test.go | 1 +
5 files changed, 155 insertions(+)
create mode 100644 integration_tests/headless/headless-basic.yaml
create mode 100644 integration_tests/headless/headless-extract-values.yaml
create mode 100644 integration_tests/headless/headless-header-action.yaml
create mode 100644 v2/cmd/integration-test/headless.go
diff --git a/integration_tests/headless/headless-basic.yaml b/integration_tests/headless/headless-basic.yaml
new file mode 100644
index 000000000..cfc7dcb3c
--- /dev/null
+++ b/integration_tests/headless/headless-basic.yaml
@@ -0,0 +1,18 @@
+id: headless-basic
+info:
+ name: Headless Basic
+ author: pdteam
+ severity: info
+ tags: headless
+
+headless:
+ - steps:
+ - action: navigate
+ args:
+ url: "{{BaseURL}}/"
+
+ - action: waitload
+ matchers:
+ - type: word
+ words:
+ - ""
\ No newline at end of file
diff --git a/integration_tests/headless/headless-extract-values.yaml b/integration_tests/headless/headless-extract-values.yaml
new file mode 100644
index 000000000..e780ac32c
--- /dev/null
+++ b/integration_tests/headless/headless-extract-values.yaml
@@ -0,0 +1,31 @@
+
+id: headless-extract-values
+info:
+ name: Headless Extract Value
+ author: pdteam
+ severity: info
+ tags: headless
+
+headless:
+ - steps:
+ - action: navigate
+ args:
+ url: "{{BaseURL}}"
+ - action: waitload
+ # From headless/extract-urls.yaml
+ - action: script
+ name: extract
+ args:
+ code: |
+ '\n' + [...new Set(Array.from(document.querySelectorAll('[src], [href], [url], [action]')).map(i => i.src || i.href || i.url || i.action))].join('\r\n') + '\n'
+
+ matchers:
+ - type: word
+ words:
+ - "test.html"
+
+ extractors:
+ - type: kval
+ part: extract
+ kval:
+ - extract
\ No newline at end of file
diff --git a/integration_tests/headless/headless-header-action.yaml b/integration_tests/headless/headless-header-action.yaml
new file mode 100644
index 000000000..ca3c329d8
--- /dev/null
+++ b/integration_tests/headless/headless-header-action.yaml
@@ -0,0 +1,24 @@
+id: headless-header-action
+info:
+ name: Headless Header Action
+ author: pdteam
+ severity: info
+ tags: headless
+
+headless:
+ - steps:
+ - action: setheader
+ args:
+ part: request
+ key: Test
+ value: test value
+
+ - action: navigate
+ args:
+ url: "{{BaseURL}}/"
+
+ - action: waitload
+ matchers:
+ - type: word
+ words:
+ - "test value"
\ No newline at end of file
diff --git a/v2/cmd/integration-test/headless.go b/v2/cmd/integration-test/headless.go
new file mode 100644
index 000000000..6039fdb64
--- /dev/null
+++ b/v2/cmd/integration-test/headless.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "net/http"
+ "net/http/httptest"
+
+ "github.com/julienschmidt/httprouter"
+
+ "github.com/projectdiscovery/nuclei/v2/pkg/testutils"
+)
+
+var headlessTestcases = map[string]testutils.TestCase{
+ "headless/headless-basic.yaml": &headlessBasic{},
+ "headless/headless-header-action.yaml": &headlessHeaderActions{},
+ "headless/headless-extract-values.yaml": &headlessExtractValues{},
+}
+
+type headlessBasic struct{}
+
+// Execute executes a test case and returns an error if occurred
+func (h *headlessBasic) Execute(filePath string) error {
+ router := httprouter.New()
+ router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ _, _ = w.Write([]byte(""))
+ })
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+
+ results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-headless")
+ if err != nil {
+ return err
+ }
+ if len(results) != 1 {
+ return errIncorrectResultsCount(results)
+ }
+ return nil
+}
+
+type headlessHeaderActions struct{}
+
+// Execute executes a test case and returns an error if occurred
+func (h *headlessHeaderActions) Execute(filePath string) error {
+ router := httprouter.New()
+ router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ testValue := r.Header.Get("test")
+ if r.Header.Get("test") != "" {
+ _, _ = w.Write([]byte("" + testValue + ""))
+ }
+ })
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+
+ results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-headless")
+ if err != nil {
+ return err
+ }
+ if len(results) != 1 {
+ return errIncorrectResultsCount(results)
+ }
+ return nil
+}
+
+type headlessExtractValues struct{}
+
+// Execute executes a test case and returns an error if occurred
+func (h *headlessExtractValues) Execute(filePath string) error {
+ router := httprouter.New()
+ router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
+ _, _ = w.Write([]byte("test"))
+ })
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+ results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-headless")
+ if err != nil {
+ return err
+ }
+ if len(results) != 3 {
+ return errIncorrectResultsCount(results)
+ }
+ return nil
+}
diff --git a/v2/cmd/integration-test/integration-test.go b/v2/cmd/integration-test/integration-test.go
index d55f74e0f..70bb193ac 100644
--- a/v2/cmd/integration-test/integration-test.go
+++ b/v2/cmd/integration-test/integration-test.go
@@ -29,6 +29,7 @@ func main() {
"workflow": workflowTestcases,
"loader": loaderTestcases,
"websocket": websocketTestCases,
+ "headless": headlessTestcases,
}
for proto, tests := range protocolTests {
if protocol == "" || protocol == proto {
From 3c88afac0ca24fd7df80de3af20a0c08f316b7e0 Mon Sep 17 00:00:00 2001
From: Mzack9999
Date: Sun, 5 Dec 2021 15:11:14 +0100
Subject: [PATCH 14/16] Fixing payloads path during validation (#1320)
* Fixing payloads path during validation
* Added GH Action for public template parsing / validation
* tracking payload errors as syntax warnings
* improving path parsing + introducing hard failure for runtime errors on validation
Co-authored-by: sandeep
---
.github/workflows/template-validate.yml | 29 +++++++++++++++++++
v2/go.mod | 8 ++---
v2/go.sum | 23 +++------------
v2/internal/runner/runner.go | 3 +-
v2/pkg/catalog/loader/loader.go | 2 ++
v2/pkg/parsers/parser.go | 6 ++--
.../protocols/common/generators/validate.go | 14 ++++++---
7 files changed, 53 insertions(+), 32 deletions(-)
create mode 100644 .github/workflows/template-validate.yml
diff --git a/.github/workflows/template-validate.yml b/.github/workflows/template-validate.yml
new file mode 100644
index 000000000..0f78d4de6
--- /dev/null
+++ b/.github/workflows/template-validate.yml
@@ -0,0 +1,29 @@
+name: 🛠 Template Validate
+
+on: [ push, pull_request ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - uses: actions/setup-go@v2
+ with:
+ go-version: 1.17
+
+ - name: Cache Go
+ id: cache-go
+ uses: actions/cache@v2
+ with:
+ path: /home/runner/go
+ key: ${{ runner.os }}-go
+
+ - name: Installing Nuclei
+ if: steps.cache-go.outputs.cache-hit != 'true'
+ run: |
+ go install github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
+
+ - name: Template Validation
+ run: |
+ nuclei -validate
+ nuclei -validate -w ./workflows
\ No newline at end of file
diff --git a/v2/go.mod b/v2/go.mod
index 709577509..490908476 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -65,6 +65,8 @@ require (
moul.io/http2curl v1.0.0
)
+require github.com/projectdiscovery/folderutil v0.0.0-20211203091551-e81604e6940e
+
require (
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
github.com/PuerkitoBio/goquery v1.6.0 // indirect
@@ -77,7 +79,6 @@ require (
github.com/bits-and-blooms/bloom/v3 v3.0.1 // indirect
github.com/c4milo/unpackit v0.1.0 // indirect
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
- github.com/dave/dst v0.26.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
@@ -92,7 +93,6 @@ require (
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
- github.com/google/go-cmp v0.5.6 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gosuri/uilive v0.0.4 // indirect
@@ -126,14 +126,10 @@ require (
github.com/zclconf/go-cty v1.8.4 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
- golang.org/x/mod v0.4.2 // indirect
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
- golang.org/x/tools v0.1.3 // indirect
- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
- mvdan.cc/gofumpt v0.1.1 // indirect
)
diff --git a/v2/go.sum b/v2/go.sum
index 731a08159..bd73d8ced 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -163,7 +163,6 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/dave/dst v0.26.2 h1:lnxLAKI3tx7MgLNVDirFCsDTlTG9nKTk7GcptKcWSwY=
github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU=
github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
@@ -596,6 +595,10 @@ github.com/projectdiscovery/fileutil v0.0.0-20210914153648-31f843feaad4/go.mod h
github.com/projectdiscovery/fileutil v0.0.0-20210926202739-6050d0acf73c/go.mod h1:U+QCpQnX8o2N2w0VUGyAzjM3yBAe4BKedVElxiImsx0=
github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5 h1:2dbm7UhrAKnccZttr78CAmG768sSCd+MBn4ayLVDeqA=
github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5/go.mod h1:U+QCpQnX8o2N2w0VUGyAzjM3yBAe4BKedVElxiImsx0=
+github.com/projectdiscovery/folderutil v0.0.0-20210804143510-68474319fd84 h1:+VqGxv8ywpIHwGGSCOcGn/q5kkuB6F1AZtY42I8VnXc=
+github.com/projectdiscovery/folderutil v0.0.0-20210804143510-68474319fd84/go.mod h1:BMqXH4jNGByVdE2iLtKvc/6XStaiZRuCIaKv1vw9PnI=
+github.com/projectdiscovery/folderutil v0.0.0-20211203091551-e81604e6940e h1:ozfSeEc5j1f7NCEZAiAskP/KYfBD/TzPmFTIfh+CEwE=
+github.com/projectdiscovery/folderutil v0.0.0-20211203091551-e81604e6940e/go.mod h1:BMqXH4jNGByVdE2iLtKvc/6XStaiZRuCIaKv1vw9PnI=
github.com/projectdiscovery/goflags v0.0.7/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
github.com/projectdiscovery/goflags v0.0.8-0.20211028121123-edf02bc05b1a h1:EzwVm8i4zmzqZX55vrDtyfogwHh8AAZ3cWCJe4fEduk=
github.com/projectdiscovery/goflags v0.0.8-0.20211028121123-edf02bc05b1a/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
@@ -640,22 +643,7 @@ github.com/projectdiscovery/stringsutil v0.0.0-20210804142656-fd3c28dbaafe/go.mo
github.com/projectdiscovery/stringsutil v0.0.0-20210823090203-2f5f137e8e1d/go.mod h1:oTRc18WBv9t6BpaN9XBY+QmG28PUpsyDzRht56Qf49I=
github.com/projectdiscovery/stringsutil v0.0.0-20210830151154-f567170afdd9 h1:xbL1/7h0k6HE3RzPdYk9W/8pUxESrGWewTaZdIB5Pes=
github.com/projectdiscovery/stringsutil v0.0.0-20210830151154-f567170afdd9/go.mod h1:oTRc18WBv9t6BpaN9XBY+QmG28PUpsyDzRht56Qf49I=
-github.com/projectdiscovery/yamldoc-go v1.0.2 h1:SKb7PHgSOXm27Zci05ba0FxpyQiu6bGEiVMEcjCK1rQ=
github.com/projectdiscovery/yamldoc-go v1.0.2/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125104740-9b1096de655d h1:sXbcjsLPDgOrlGXgCKbT6MMyH/hTY3OJhhwsyM2bNlI=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125104740-9b1096de655d/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125105154-082a0a3cc326 h1:/fGqkG8GlfdvlTCfvAoSA/WgEAJrmCnW5qtdd7QXnwA=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125105154-082a0a3cc326/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125110259-585ff5584784 h1:Be2eD7oXNvCbFufVhvkiO5a0SRVN+Ri2V9pXKL2uJp8=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125110259-585ff5584784/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125112758-99d87632e49a h1:xGeZvil8Fe5LpGJbTGZGafnnbedNGtVcvLv3nYtmhXQ=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125112758-99d87632e49a/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125135034-67f4c31feb2b h1:oSBnxdyyDU/WpNKUAXrhydgx5+JtDT7KfJR+hOEaBXk=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125135034-67f4c31feb2b/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125135235-2e6dd74132d0 h1:mOptvTJ32yUuqQjjSfiPkPCelTWzqnts92uNOZBXZZo=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125135235-2e6dd74132d0/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125140040-b396ca47606e h1:0ZxOM0Q0/ESa24L/vq3fxs9YipxfHR4Y3jM/H2ReJ5E=
-github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211125140040-b396ca47606e/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6nhz0rK/H9sUjq1ciZu24=
github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211126104922-00d2c6bb43b6 h1:DvWRQpw7Ib2CRL3ogYm/BWM+X0UGPfz1n9Ix9YKgFM8=
github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211126104922-00d2c6bb43b6/go.mod h1:8OfZj8p/axkUM/TJoS/O9LDjj/S8u17rxRbqluE9CU4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -907,7 +895,6 @@ golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hM
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1126,7 +1113,6 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1267,7 +1253,6 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
-mvdan.cc/gofumpt v0.1.1 h1:bi/1aS/5W00E2ny5q65w9SnKpWEF/UIOqDYBILpo9rA=
mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go
index a5aea7e9e..0d33511b8 100644
--- a/v2/internal/runner/runner.go
+++ b/v2/internal/runner/runner.go
@@ -279,7 +279,7 @@ func (r *Runner) RunEnumeration() error {
if err := store.ValidateTemplates(r.options.Templates, r.options.Workflows); err != nil {
return err
}
- if stats.GetValue(parsers.SyntaxErrorStats) == 0 && stats.GetValue(parsers.SyntaxWarningStats) == 0 {
+ if stats.GetValue(parsers.SyntaxErrorStats) == 0 && stats.GetValue(parsers.SyntaxWarningStats) == 0 && stats.GetValue(parsers.RuntimeWarningsStats) == 0 {
gologger.Info().Msgf("All templates validated successfully\n")
} else {
return errors.New("encountered errors while performing template validation")
@@ -362,6 +362,7 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
// Display stats for any loaded templates' syntax warnings or errors
stats.Display(parsers.SyntaxWarningStats)
stats.Display(parsers.SyntaxErrorStats)
+ stats.Display(parsers.RuntimeWarningsStats)
builder := &strings.Builder{}
if r.templatesConfig != nil && r.templatesConfig.NucleiLatestVersion != "" {
diff --git a/v2/pkg/catalog/loader/loader.go b/v2/pkg/catalog/loader/loader.go
index 12ddcfc39..23dfd980a 100644
--- a/v2/pkg/catalog/loader/loader.go
+++ b/v2/pkg/catalog/loader/loader.go
@@ -12,6 +12,7 @@ import (
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
+ "github.com/projectdiscovery/nuclei/v2/pkg/utils/stats"
)
// Config contains the configuration options for the loader
@@ -218,6 +219,7 @@ func (store *Store) LoadTemplates(templatesList []string) []*templates.Template
if loaded {
parsed, err := templates.Parse(templatePath, store.preprocessor, store.config.ExecutorOptions)
if err != nil {
+ stats.Increment(parsers.RuntimeWarningsStats)
gologger.Warning().Msgf("Could not parse template %s: %s\n", templatePath, err)
} else if parsed != nil {
loadedTemplates = append(loadedTemplates, parsed)
diff --git a/v2/pkg/parsers/parser.go b/v2/pkg/parsers/parser.go
index e26e7488e..c63922466 100644
--- a/v2/pkg/parsers/parser.go
+++ b/v2/pkg/parsers/parser.go
@@ -108,8 +108,9 @@ var (
)
const (
- SyntaxWarningStats = "syntax-warnings"
- SyntaxErrorStats = "syntax-errors"
+ SyntaxWarningStats = "syntax-warnings"
+ SyntaxErrorStats = "syntax-errors"
+ RuntimeWarningsStats = "runtime-warnings"
)
func init() {
@@ -118,6 +119,7 @@ func init() {
stats.NewEntry(SyntaxWarningStats, "Found %d templates with syntax warning (use -validate flag for further examination)")
stats.NewEntry(SyntaxErrorStats, "Found %d templates with syntax error (use -validate flag for further examination)")
+ stats.NewEntry(RuntimeWarningsStats, "Found %d templates with runtime error (use -validate flag for further examination)")
}
// ParseTemplate parses a template and returns a *templates.Template structure
diff --git a/v2/pkg/protocols/common/generators/validate.go b/v2/pkg/protocols/common/generators/validate.go
index 305cae092..b04f8034c 100644
--- a/v2/pkg/protocols/common/generators/validate.go
+++ b/v2/pkg/protocols/common/generators/validate.go
@@ -4,9 +4,9 @@ import (
"errors"
"fmt"
"os"
- "path/filepath"
"strings"
+ "github.com/projectdiscovery/folderutil"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
)
@@ -26,10 +26,16 @@ func (g *PayloadGenerator) validate(payloads map[string]interface{}, templatePat
}
changed := false
- pathTokens := strings.Split(templatePath, string(os.PathSeparator))
- for i := range pathTokens {
- payloadPath := filepath.Join(filepath.Join(pathTokens[:i]...), payloadType)
+ templatePathInfo, err := folderutil.NewPathInfo(templatePath)
+ if err != nil {
+ return err
+ }
+ payloadPathsToProbe, err := templatePathInfo.MeshWith(payloadType)
+ if err != nil {
+ return err
+ }
+ for _, payloadPath := range payloadPathsToProbe {
if fileExists(payloadPath) {
payloads[name] = payloadPath
changed = true
From fb3b4fc510f7406dd7722e5b715b3fa32f0102c7 Mon Sep 17 00:00:00 2001
From: sandeep
Date: Sun, 5 Dec 2021 19:45:44 +0530
Subject: [PATCH 15/16] version update
---
v2/pkg/catalog/config/config.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/v2/pkg/catalog/config/config.go b/v2/pkg/catalog/config/config.go
index 87e6c672d..bb5cfb24f 100644
--- a/v2/pkg/catalog/config/config.go
+++ b/v2/pkg/catalog/config/config.go
@@ -26,7 +26,7 @@ type Config struct {
const nucleiConfigFilename = ".templates-config.json"
// Version is the current version of nuclei
-const Version = `2.5.4-dev`
+const Version = `2.5.4`
func getConfigDetails() (string, error) {
homeDir, err := os.UserHomeDir()
From df55f7a2eb591a7949b5c66a9c54db54aa28f450 Mon Sep 17 00:00:00 2001
From: Sandeep Singh
Date: Sun, 5 Dec 2021 20:14:16 +0530
Subject: [PATCH 16/16] Disabling no-sandbox in headless engine (#1135)
* Disabling no-sandbox in headless engine
* limiting disabling sandbox to bare minimum
* adding warnings related to linux os and root user requirement
Co-authored-by: mzack
---
v2/cmd/nuclei/main.go | 2 +-
v2/internal/runner/runner.go | 3 +++
v2/pkg/protocols/headless/engine/engine.go | 13 ++++++++++++-
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/v2/cmd/nuclei/main.go b/v2/cmd/nuclei/main.go
index 059a96167..bd015fede 100644
--- a/v2/cmd/nuclei/main.go
+++ b/v2/cmd/nuclei/main.go
@@ -134,7 +134,7 @@ on extensive configurability, massive extensibility and ease of use.`)
)
createGroup(flagSet, "headless", "Headless",
- flagSet.BoolVar(&options.Headless, "headless", false, "enable templates that require headless browser support"),
+ flagSet.BoolVar(&options.Headless, "headless", false, "enable templates that require headless browser support (root user on linux will disable sandbox)"),
flagSet.IntVar(&options.PageTimeout, "page-timeout", 20, "seconds to wait for each page in headless mode"),
flagSet.BoolVarP(&options.ShowBrowser, "show-browser", "sb", false, "show the browser on the screen when running templates with headless mode"),
flagSet.BoolVarP(&options.UseInstalledChrome, "system-chrome", "sc", false, "Use local installed chrome browser instead of nuclei installed"),
diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go
index 0d33511b8..b71587267 100644
--- a/v2/internal/runner/runner.go
+++ b/v2/internal/runner/runner.go
@@ -76,6 +76,9 @@ func New(options *types.Options) (*Runner, error) {
gologger.Warning().Msgf("Could not update templates: %s\n", err)
}
if options.Headless {
+ if engine.MustDisableSandbox() {
+ gologger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n")
+ }
browser, err := engine.New(options)
if err != nil {
return nil, err
diff --git a/v2/pkg/protocols/headless/engine/engine.go b/v2/pkg/protocols/headless/engine/engine.go
index d73e79044..6c1046b67 100644
--- a/v2/pkg/protocols/headless/engine/engine.go
+++ b/v2/pkg/protocols/headless/engine/engine.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"net/http"
"os"
+ "runtime"
"strings"
"github.com/corpix/uarand"
@@ -44,12 +45,15 @@ func New(options *types.Options) (*Browser, error) {
Set("disable-notifications", "true").
Set("hide-scrollbars", "true").
Set("window-size", fmt.Sprintf("%d,%d", 1080, 1920)).
- Set("no-sandbox", "true").
Set("mute-audio", "true").
Set("incognito", "true").
Delete("use-mock-keychain").
UserDataDir(dataStore)
+ if MustDisableSandbox() {
+ chromeLauncher = chromeLauncher.NoSandbox(true)
+ }
+
if options.UseInstalledChrome {
if chromePath, hasChrome := launcher.LookPath(); hasChrome {
chromeLauncher.Bin(chromePath)
@@ -105,6 +109,13 @@ func New(options *types.Options) (*Browser, error) {
return engine, nil
}
+// MustDisableSandbox determines if the current os and user needs sandbox mode disabled
+func MustDisableSandbox() bool {
+ // linux with root user needs "--no-sandbox" option
+ // https://github.com/chromium/chromium/blob/c4d3c31083a2e1481253ff2d24298a1dfe19c754/chrome/test/chromedriver/client/chromedriver.py#L209
+ return runtime.GOOS == "linux" && os.Geteuid() == 0
+}
+
// Close closes the browser engine
func (b *Browser) Close() {
b.engine.Close()