+
+CVE ID for the template
+
+
+
+Examples:
+
+
+```yaml
+cve-id: CVE-2020-14420
+```
+
+
+
+
+
+
+CWE ID for the template.
+
+
+
+Examples:
+
+
+```yaml
+cwe-id: CWE-22
+```
+
+
+
+
+
+
+CVSS Metrics for the template.
+
+
+
+Examples:
+
+
+```yaml
+cvss-metrics: 3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
+```
+
+
+
+
+
+
+CVSS Score for the template.
+
+
+
+Examples:
+
+
+```yaml
+cvss-score: "9.8"
+```
+
+
+
+
+
diff --git a/nuclei-jsonschema.json b/nuclei-jsonschema.json
index 6092a125a..c26306c6a 100755
--- a/nuclei-jsonschema.json
+++ b/nuclei-jsonschema.json
@@ -2,17 +2,34 @@
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/templates.Template",
"definitions": {
- "severity.SeverityHolder": {
- "enum": [
- "info",
- "low",
- "medium",
- "high",
- "critical"
- ],
- "type": "string",
- "title": "severity of the template",
- "description": "Seriousness of the implications of the template"
+ "model.Classification": {
+ "properties": {
+ "cve-id": {
+ "$ref": "#/definitions/stringslice.StringSlice",
+ "title": "cve ids for the template",
+ "description": "CVE IDs for the template"
+ },
+ "cwe-id": {
+ "$ref": "#/definitions/stringslice.StringSlice",
+ "title": "cwe ids for the template",
+ "description": "CWE IDs for the template"
+ },
+ "cvss-metrics": {
+ "type": "string",
+ "title": "cvss metrics for the template",
+ "description": "CVSS Metrics for the template",
+ "examples": [
+ "3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
+ ]
+ },
+ "cvss-score": {
+ "type": "number",
+ "title": "cvss score for the template",
+ "description": "CVSS Score for the template"
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
},
"model.Info": {
"properties": {
@@ -26,12 +43,12 @@
},
"author": {
"$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/model.StringSlice",
+ "$ref": "#/definitions/stringslice.StringSlice",
"title": "author of the template",
"description": "Author is the author of the template"
},
"tags": {
- "$ref": "#/definitions/model.StringSlice",
+ "$ref": "#/definitions/stringslice.StringSlice",
"title": "tags of the template",
"description": "Any tags for the template"
},
@@ -44,13 +61,13 @@
]
},
"reference": {
- "$ref": "#/definitions/model.StringSlice",
+ "$ref": "#/definitions/stringslice.StringSlice",
"title": "references for the template",
"description": "Links relevant to the template"
},
"severity": {
"$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/severity.SeverityHolder"
+ "$ref": "#/definitions/severity.Holder"
},
"additional-fields": {
"patternProperties": {
@@ -61,12 +78,38 @@
"type": "object",
"title": "additional metadata for the template",
"description": "Additional metadata fields for the template"
+ },
+ "classification": {
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "$ref": "#/definitions/model.Classification",
+ "title": "classification info for the template",
+ "description": "Classification information for the template"
+ },
+ "remediation": {
+ "type": "string",
+ "title": "remediation steps for the template",
+ "description": "In-depth explanation on how to fix the issues found by the template",
+ "examples": [
+ "Change the default administrative username and password of Apache ActiveMQ by editing the file jetty-realm.properties"
+ ]
}
},
"additionalProperties": false,
"type": "object"
},
- "model.StringSlice": {
+ "severity.Holder": {
+ "enum": [
+ "info",
+ "low",
+ "medium",
+ "high",
+ "critical"
+ ],
+ "type": "string",
+ "title": "severity of the template",
+ "description": "Seriousness of the implications of the template"
+ },
+ "stringslice.StringSlice": {
"oneOf": [
{
"type": "string"
@@ -885,7 +928,7 @@
"description": "Template or directory to execute as part of workflow"
},
"tags": {
- "$ref": "#/definitions/model.StringSlice",
+ "$ref": "#/definitions/stringslice.StringSlice",
"title": "tags to execute",
"description": "Tags to run template based on"
},
diff --git a/v2/cmd/cve-annotate/main.go b/v2/cmd/cve-annotate/main.go
new file mode 100644
index 000000000..3a0f1ddf8
--- /dev/null
+++ b/v2/cmd/cve-annotate/main.go
@@ -0,0 +1,159 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "regexp"
+ "strings"
+
+ "github.com/Ice3man543/nvd"
+ "github.com/projectdiscovery/nuclei/v2/pkg/catalog"
+)
+
+var (
+ input = flag.String("i", "", "Templates to annotate")
+ templateDir = flag.String("d", "", "Custom template directory for update")
+)
+
+func main() {
+ flag.Parse()
+
+ if *input == "" || *templateDir == "" {
+ log.Fatalf("invalid input, see -h\n")
+ }
+
+ if err := process(); err != nil {
+ log.Fatalf("could not process: %s\n", err)
+ }
+}
+
+func process() error {
+ tempDir, err := ioutil.TempDir("", "nuclei-nvd-%s")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(tempDir)
+
+ client, err := nvd.NewClient(tempDir)
+ if err != nil {
+ return err
+ }
+ catalog := catalog.New(*templateDir)
+
+ paths, err := catalog.GetTemplatePath(*input)
+ if err != nil {
+ return err
+ }
+ for _, path := range paths {
+ data, err := ioutil.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ getCVEData(client, path, string(data))
+ }
+ return nil
+}
+
+var (
+ idRegex = regexp.MustCompile("id: ([C|c][V|v][E|e]-[0-9]+-[0-9]+)")
+ severityRegex = regexp.MustCompile(`severity: ([a-z]+)`)
+)
+
+func getCVEData(client *nvd.Client, filePath, data string) {
+ matches := idRegex.FindAllStringSubmatch(data, 1)
+ if len(matches) == 0 {
+ return
+ }
+ cveName := matches[0][1]
+
+ severityMatches := severityRegex.FindAllStringSubmatch(data, 1)
+ if len(matches) == 0 {
+ return
+ }
+ severityValue := severityMatches[0][1]
+
+ cveItem, err := client.FetchCVE(cveName)
+ if err != nil {
+ log.Printf("Could not fetch cve %s: %s\n", cveName, err)
+ return
+ }
+ var cweID []string
+ for _, problemData := range cveItem.CVE.Problemtype.ProblemtypeData {
+ for _, description := range problemData.Description {
+ cweID = append(cweID, description.Value)
+ }
+ }
+ cvssScore := cveItem.Impact.BaseMetricV3.CvssV3.BaseScore
+ cvssMetrics := cveItem.Impact.BaseMetricV3.CvssV3.VectorString
+
+ // Perform some hacky string replacement to place the metadata in templates
+ infoBlockIndexData := data[strings.Index(data, "info:"):]
+ requestsIndex := strings.Index(infoBlockIndexData, "requests:")
+ networkIndex := strings.Index(infoBlockIndexData, "network:")
+ if requestsIndex == -1 && networkIndex == -1 {
+ return
+ }
+ if networkIndex != -1 {
+ requestsIndex = networkIndex
+ }
+ infoBlockData := infoBlockIndexData[:requestsIndex]
+ infoBlockClean := strings.TrimRight(infoBlockData, "\n")
+
+ newInfoBlock := infoBlockClean
+ var changed bool
+
+ if newSeverity := isSeverityMatchingCvssScore(severityValue, cvssScore); newSeverity != "" {
+ changed = true
+ newInfoBlock = strings.ReplaceAll(newInfoBlock, severityMatches[0][0], "severity: "+newSeverity)
+ fmt.Printf("Adjusting severity for %s from %s=>%s (%.2f)\n", filePath, severityValue, newSeverity, cvssScore)
+ }
+ // Start with additional-fields as that is the one most likely to break stuff.
+ if !strings.Contains(infoBlockClean, "classification") && (cvssScore != 0 && cvssMetrics != "") {
+ changed = true
+ newInfoBlock = newInfoBlock + fmt.Sprintf("\n classification:\n cvss-metrics: %s\n cvss-score: %.2f\n cve-id: %s", cvssMetrics, cvssScore, cveName)
+ if len(cweID) > 0 && (cweID[0] != "NVD-CWE-Other" && cweID[0] != "NVD-CWE-noinfo") {
+ newInfoBlock = newInfoBlock + fmt.Sprintf("\n cwe-id: %s", strings.Join(cweID, ","))
+ }
+ }
+ // If there is no description field, fill the description from CVE information
+ if !strings.Contains(infoBlockClean, "description:") {
+ changed = true
+ newInfoBlock = newInfoBlock + fmt.Sprintf("\n description: %s", fmt.Sprintf("%q", cveItem.CVE.Description.DescriptionData[0].Value))
+ }
+ if !strings.Contains(infoBlockClean, "reference:") && len(cveItem.CVE.References.ReferenceData) > 0 {
+ changed = true
+ newInfoBlock = newInfoBlock + "\n reference:"
+ for _, reference := range cveItem.CVE.References.ReferenceData {
+ newInfoBlock = newInfoBlock + fmt.Sprintf("\n - %s", reference.URL)
+ }
+ }
+ newTemplate := strings.ReplaceAll(data, infoBlockClean, newInfoBlock)
+ if changed {
+ _ = ioutil.WriteFile(filePath, []byte(newTemplate), 0777)
+ fmt.Printf("Wrote updated template to %s\n", filePath)
+ }
+}
+
+func isSeverityMatchingCvssScore(severity string, score float64) string {
+ if score == 0.0 {
+ return ""
+ }
+ var expected string
+
+ if score >= 0.1 && score <= 3.9 {
+ expected = "low"
+ } else if score >= 4.0 && score <= 6.9 {
+ expected = "medium"
+ } else if score >= 7.0 && score <= 8.9 {
+ expected = "high"
+ } else if score >= 9.0 && score <= 10.0 {
+ expected = "critical"
+ }
+ if expected != "" && expected != severity {
+ return expected
+ }
+ return ""
+}
diff --git a/v2/go.mod b/v2/go.mod
index a509f4c29..7a2b6c457 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -3,6 +3,7 @@ module github.com/projectdiscovery/nuclei/v2
go 1.16
require (
+ github.com/Ice3man543/nvd v1.0.6
github.com/Knetic/govaluate v3.0.0+incompatible
github.com/akrylysov/pogreb v0.10.1 // indirect
github.com/alecthomas/jsonschema v0.0.0-20210818095345-1014919a589c
@@ -13,7 +14,6 @@ require (
github.com/bluele/gcache v0.0.2
github.com/c4milo/unpackit v0.1.0 // indirect
github.com/corpix/uarand v0.1.1
- github.com/davecgh/go-spew v1.1.1
github.com/go-rod/rod v0.91.1
github.com/google/go-github v17.0.0+incompatible
github.com/gosuri/uilive v0.0.4 // indirect
diff --git a/v2/go.sum b/v2/go.sum
index 97e87b5d9..37e3bc6cb 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -37,6 +37,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Ice3man543/nvd v1.0.6 h1:QnCqnuYAA9tY2F38oNXp/kFV5fnYq+44mmcDFhKyawc=
+github.com/Ice3man543/nvd v1.0.6/go.mod h1:0DxLJk6revOcJKiZxa2K+rNF/HO1zJO97lqQtXhXfSc=
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic=
@@ -45,9 +47,10 @@ github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHS
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
+github.com/PuerkitoBio/goquery v1.6.0 h1:j7taAbelrdcsOlGeMenZxc2AWXD5fieT1/znArdnx94=
+github.com/PuerkitoBio/goquery v1.6.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
-github.com/akrylysov/pogreb v0.10.0 h1:pVKi+uf3EzZUmiwr9bZnPk4W379KP8QsFzAa9IUuOog=
github.com/akrylysov/pogreb v0.10.0/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
@@ -55,6 +58,8 @@ github.com/alecthomas/jsonschema v0.0.0-20210818095345-1014919a589c h1:oJsq4z4xK
github.com/alecthomas/jsonschema v0.0.0-20210818095345-1014919a589c/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
+github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/andygrunwald/go-jira v1.14.0 h1:7GT/3qhar2dGJ0kq8w0d63liNyHOnxZsUZ9Pe4+AKBI=
github.com/andygrunwald/go-jira v1.14.0/go.mod h1:KMo2f4DgMZA1C9FdImuLc04x4WQhn5derQpnsuBFgqE=
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
@@ -96,6 +101,8 @@ github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U=
github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/daehee/nvd v1.0.4 h1:qC0kJ68vAYS86v8GwBORReBhyC5yUaUzsBokxjlsT98=
+github.com/daehee/nvd v1.0.4/go.mod h1:iBRJHIdIs+ylfq8630my2eMw8kwzH4Z7qsetjJZxCzs=
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=
@@ -229,7 +236,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA=
github.com/itchyny/gojq v0.12.4 h1:8zgOZWMejEWCLjbF/1mWY7hY7QEARm7dtuhC6Bp4R8o=
@@ -276,13 +282,11 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
-github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@@ -510,6 +514,7 @@ 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 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/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=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -614,7 +619,6 @@ golang.org/x/sys v0.0.0-20210415045647-66c3f260301c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -705,7 +709,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
diff --git a/v2/internal/runner/banner.go b/v2/internal/runner/banner.go
index eed5277d8..b75f09c33 100644
--- a/v2/internal/runner/banner.go
+++ b/v2/internal/runner/banner.go
@@ -20,6 +20,6 @@ func showBanner() {
gologger.Print().Msgf("%s\n", banner)
gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n")
- gologger.Error().Label("WRN").Msgf("Use with caution. You are responsible for your actions\n")
+ gologger.Error().Label("WRN").Msgf("Use with caution. You are responsible for your actions.\n")
gologger.Error().Label("WRN").Msgf("Developers assume no liability and are not responsible for any misuse or damage.\n")
}
diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go
index 2617c90c2..c2c791e8b 100644
--- a/v2/internal/runner/runner.go
+++ b/v2/internal/runner/runner.go
@@ -189,7 +189,7 @@ func New(options *types.Options) (*Runner, error) {
}
// Create the output file if asked
- outputWriter, err := output.NewStandardWriter(!options.NoColor, options.NoMeta, options.NoTimestamp, options.JSON, options.Output, options.TraceLogFile)
+ outputWriter, err := output.NewStandardWriter(!options.NoColor, options.NoMeta, options.NoTimestamp, options.JSON, options.JSONRequests, options.Output, options.TraceLogFile)
if err != nil {
return nil, errors.Wrap(err, "could not create output file")
}
@@ -439,7 +439,7 @@ func (r *Runner) RunEnumeration() error {
}
templatesMap := make(map[string]*templates.Template)
for _, v := range store.Templates() {
- templatesMap[v.ID] = v
+ templatesMap[v.Path] = v
}
originalTemplatesCount := len(store.Templates())
clusterCount := 0
@@ -471,6 +471,7 @@ func (r *Runner) RunEnumeration() error {
finalTemplates = append(finalTemplates, cluster...)
}
}
+
finalTemplates = append(finalTemplates, store.Workflows()...)
var totalRequests int64
diff --git a/v2/nuclei-jsonschema.json b/v2/nuclei-jsonschema.json
deleted file mode 100755
index 6092a125a..000000000
--- a/v2/nuclei-jsonschema.json
+++ /dev/null
@@ -1,914 +0,0 @@
-{
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/templates.Template",
- "definitions": {
- "severity.SeverityHolder": {
- "enum": [
- "info",
- "low",
- "medium",
- "high",
- "critical"
- ],
- "type": "string",
- "title": "severity of the template",
- "description": "Seriousness of the implications of the template"
- },
- "model.Info": {
- "properties": {
- "name": {
- "type": "string",
- "title": "name of the template",
- "description": "Name is a short summary of what the template does",
- "examples": [
- "Nagios Default Credentials Check"
- ]
- },
- "author": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/model.StringSlice",
- "title": "author of the template",
- "description": "Author is the author of the template"
- },
- "tags": {
- "$ref": "#/definitions/model.StringSlice",
- "title": "tags of the template",
- "description": "Any tags for the template"
- },
- "description": {
- "type": "string",
- "title": "description of the template",
- "description": "In-depth explanation on what the template does",
- "examples": [
- "Bower is a package manager which stores packages informations in bower.json file"
- ]
- },
- "reference": {
- "$ref": "#/definitions/model.StringSlice",
- "title": "references for the template",
- "description": "Links relevant to the template"
- },
- "severity": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/severity.SeverityHolder"
- },
- "additional-fields": {
- "patternProperties": {
- ".*": {
- "type": "string"
- }
- },
- "type": "object",
- "title": "additional metadata for the template",
- "description": "Additional metadata fields for the template"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "model.StringSlice": {
- "oneOf": [
- {
- "type": "string"
- },
- {
- "type": "array"
- }
- ]
- },
- "extractors.Extractor": {
- "required": [
- "type"
- ],
- "properties": {
- "name": {
- "type": "string",
- "title": "name of the extractor",
- "description": "Name of the extractor"
- },
- "type": {
- "enum": [
- "regex",
- "kval",
- "json",
- "xpath"
- ],
- "type": "string",
- "title": "type of the extractor",
- "description": "Type of the extractor"
- },
- "regex": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "regex to extract from part",
- "description": "Regex to extract from part"
- },
- "group": {
- "type": "integer",
- "title": "group to extract from regex",
- "description": "Group to extract from regex"
- },
- "kval": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "kval pairs to extract from response",
- "description": "Kval pairs to extract from response"
- },
- "json": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "json jq expressions to extract data",
- "description": "JSON JQ expressions to evaluate from response part"
- },
- "xpath": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "html xpath expressions to extract data",
- "description": "XPath allows using xpath expressions to extract items from html response"
- },
- "attribute": {
- "type": "string",
- "title": "optional attribute to extract from xpath",
- "description": "Optional attribute to extract from response XPath"
- },
- "part": {
- "type": "string",
- "title": "part of response to extract data from",
- "description": "Part of the request response to extract data from"
- },
- "internal": {
- "type": "boolean",
- "title": "mark extracted value for internal variable use",
- "description": "Internal when set to true will allow using the value extracted in the next request for some protocols"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "matchers.Matcher": {
- "required": [
- "type"
- ],
- "properties": {
- "type": {
- "enum": [
- "status",
- "size",
- "word",
- "regex",
- "dsl"
- ],
- "type": "string",
- "title": "type of matcher",
- "description": "Type of the matcher"
- },
- "condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between matcher variables",
- "description": "Condition between the matcher variables"
- },
- "part": {
- "type": "string",
- "title": "part of response to match",
- "description": "Part of response to match data from"
- },
- "negative": {
- "type": "boolean",
- "title": "negative specifies if match reversed",
- "description": "Negative specifies if the match should be reversed. It will only match if the condition is not true"
- },
- "name": {
- "type": "string",
- "title": "name of the matcher",
- "description": "Name of the matcher"
- },
- "status": {
- "items": {
- "type": "integer"
- },
- "type": "array",
- "title": "status to match",
- "description": "Status to match for the response"
- },
- "size": {
- "items": {
- "type": "integer"
- },
- "type": "array",
- "title": "acceptable size for response",
- "description": "Size is the acceptable size for the response"
- },
- "words": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "words to match in response",
- "description": " Words contains word patterns required to be present in the response part"
- },
- "regex": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "regex to match in response",
- "description": "Regex contains regex patterns required to be present in the response part"
- },
- "binary": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "binary patterns to match in response",
- "description": "Binary are the binary patterns required to be present in the response part"
- },
- "dsl": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "dsl expressions to match in response",
- "description": "DSL are the dsl expressions that will be evaluated as part of nuclei matching rules"
- },
- "encoding": {
- "enum": [
- "hex"
- ],
- "type": "string",
- "title": "encoding for word field",
- "description": "Optional encoding for the word fields"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "dns.Request": {
- "properties": {
- "matchers": {
- "items": {
- "$ref": "#/definitions/matchers.Matcher"
- },
- "type": "array",
- "title": "matchers to run on response",
- "description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
- },
- "extractors": {
- "items": {
- "$ref": "#/definitions/extractors.Extractor"
- },
- "type": "array",
- "title": "extractors to run on response",
- "description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
- },
- "matchers-condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between the matchers",
- "description": "Conditions between the matchers"
- },
- "id": {
- "type": "string",
- "title": "id of the dns request",
- "description": "ID is the optional ID of the DNS Request"
- },
- "name": {
- "type": "string",
- "title": "hostname to make dns request for",
- "description": "Name is the Hostname to make DNS request for"
- },
- "type": {
- "enum": [
- "A",
- "NS",
- "DS",
- "CNAME",
- "SOA",
- "PTR",
- "MX",
- "TXT",
- "AAAA"
- ],
- "type": "string",
- "title": "type of dns request to make",
- "description": "Type is the type of DNS request to make"
- },
- "class": {
- "enum": [
- "inet",
- "csnet",
- "chaos",
- "hesiod",
- "none",
- "any"
- ],
- "type": "string",
- "title": "class of DNS request",
- "description": "Class is the class of the DNS request"
- },
- "retries": {
- "type": "integer",
- "title": "retries for dns request",
- "description": "Retries is the number of retries for the DNS request"
- },
- "recursion": {
- "type": "boolean",
- "title": "recurse all servers",
- "description": "Recursion determines if resolver should recurse all records to get fresh results"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "file.Request": {
- "properties": {
- "matchers": {
- "items": {
- "$ref": "#/definitions/matchers.Matcher"
- },
- "type": "array",
- "title": "matchers to run on response",
- "description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
- },
- "extractors": {
- "items": {
- "$ref": "#/definitions/extractors.Extractor"
- },
- "type": "array",
- "title": "extractors to run on response",
- "description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
- },
- "matchers-condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between the matchers",
- "description": "Conditions between the matchers"
- },
- "extensions": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "extensions to match",
- "description": "List of extensions to perform matching on"
- },
- "denylist": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "extensions to deny match",
- "description": "List of file extensions to deny during matching"
- },
- "id": {
- "type": "string",
- "title": "id of the request",
- "description": "ID is the optional ID for the request"
- },
- "max-size": {
- "type": "integer",
- "title": "max size data to run request on",
- "description": "Maximum size of the file to run request on"
- },
- "no-recursive": {
- "type": "boolean",
- "title": "do not perform recursion",
- "description": "Specifies whether to not do recursive checks if folders are provided"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "headless.Request": {
- "properties": {
- "id": {
- "type": "string",
- "title": "id of the request",
- "description": "Optional ID of the headless request"
- },
- "steps": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/engine.Action"
- },
- "type": "array",
- "title": "list of actions for headless request",
- "description": "List of actions to run for headless request"
- },
- "matchers": {
- "items": {
- "$ref": "#/definitions/matchers.Matcher"
- },
- "type": "array",
- "title": "matchers to run on response",
- "description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
- },
- "extractors": {
- "items": {
- "$ref": "#/definitions/extractors.Extractor"
- },
- "type": "array",
- "title": "extractors to run on response",
- "description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
- },
- "matchers-condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between the matchers",
- "description": "Conditions between the matchers"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "engine.Action": {
- "required": [
- "action"
- ],
- "properties": {
- "args": {
- "patternProperties": {
- ".*": {
- "type": "string"
- }
- },
- "type": "object",
- "title": "arguments for headless action",
- "description": "Args contain arguments for the headless action"
- },
- "name": {
- "type": "string",
- "title": "name for headless action",
- "description": "Name is the name assigned to the headless action"
- },
- "description": {
- "type": "string",
- "title": "description for headless action",
- "description": "Description of the headless action"
- },
- "action": {
- "enum": [
- "navigate",
- "script",
- "click",
- "rightclick",
- "text",
- "screenshot",
- "time",
- "select",
- "files",
- "waitload",
- "getresource",
- "extract",
- "setmethod",
- "addheader",
- "setheader",
- "deleteheader",
- "setbody",
- "waitevent",
- "keyboard",
- "debug",
- "sleep"
- ],
- "type": "string",
- "title": "action to perform",
- "description": "Type of actions to perform"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "http.Request": {
- "properties": {
- "matchers": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/matchers.Matcher"
- },
- "type": "array",
- "title": "matchers to run on response",
- "description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
- },
- "extractors": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/extractors.Extractor"
- },
- "type": "array",
- "title": "extractors to run on response",
- "description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
- },
- "matchers-condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between the matchers",
- "description": "Conditions between the matchers"
- },
- "path": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "path(s) for the http request",
- "description": "Path(s) to send http requests to"
- },
- "raw": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "description": "HTTP Requests in Raw Format"
- },
- "id": {
- "type": "string",
- "title": "id for the http request",
- "description": "ID for the HTTP Request"
- },
- "name": {
- "type": "string",
- "title": "name for the http request",
- "description": "Optional name for the HTTP Request"
- },
- "attack": {
- "enum": [
- "sniper",
- "pitchfork",
- "clusterbomb"
- ],
- "type": "string",
- "title": "attack is the payload combination",
- "description": "Attack is the type of payload combinations to perform"
- },
- "method": {
- "enum": [
- "GET",
- "HEAD",
- "POST",
- "PUT",
- "DELETE",
- "CONNECT",
- "OPTIONS",
- "TRACE",
- "PATCH"
- ],
- "type": "string",
- "title": "method is the http request method",
- "description": "Method is the HTTP Request Method"
- },
- "body": {
- "type": "string",
- "title": "body is the http request body",
- "description": "Body is an optional parameter which contains HTTP Request body"
- },
- "payloads": {
- "patternProperties": {
- ".*": {
- "additionalProperties": true
- }
- },
- "type": "object",
- "title": "payloads for the http request",
- "description": "Payloads contains any payloads for the current request"
- },
- "headers": {
- "patternProperties": {
- ".*": {
- "type": "string"
- }
- },
- "type": "object",
- "title": "headers to send with the http request",
- "description": "Headers contains HTTP Headers to send with the request"
- },
- "race_count": {
- "type": "integer",
- "title": "number of times to repeat request in race condition",
- "description": "Number of times to send a request in Race Condition Attack"
- },
- "max-redirects": {
- "type": "integer",
- "title": "maximum number of redirects to follow",
- "description": "Maximum number of redirects that should be followed"
- },
- "pipeline-concurrent-connections": {
- "type": "integer",
- "title": "number of pipelining connections",
- "description": "Number of connections to create during pipelining"
- },
- "pipeline-requests-per-connection": {
- "type": "integer",
- "title": "number of requests to send per pipelining connections",
- "description": "Number of requests to send per connection when pipelining"
- },
- "threads": {
- "type": "integer",
- "title": "threads for sending requests",
- "description": "Threads specifies number of threads to use sending requests. This enables Connection Pooling"
- },
- "max-size": {
- "type": "integer",
- "title": "maximum http response body size",
- "description": "Maximum size of http response body to read in bytes"
- },
- "cookie-reuse": {
- "type": "boolean",
- "title": "optional cookie reuse enable",
- "description": "Optional setting that enables cookie reuse"
- },
- "redirects": {
- "type": "boolean",
- "title": "follow http redirects",
- "description": "Specifies whether redirects should be followed by the HTTP Client"
- },
- "pipeline": {
- "type": "boolean",
- "title": "perform HTTP 1.1 pipelining",
- "description": "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining"
- },
- "unsafe": {
- "type": "boolean",
- "title": "use rawhttp non-strict-rfc client",
- "description": "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests"
- },
- "race": {
- "type": "boolean",
- "title": "perform race-http request coordination attack",
- "description": "Race determines if all the request have to be attempted at the same time (Race Condition)"
- },
- "req-condition": {
- "type": "boolean",
- "title": "preserve request history",
- "description": "Automatically assigns numbers to requests and preserves their history"
- },
- "stop-at-first-match": {
- "type": "boolean",
- "title": "stop at first match",
- "description": "Stop the execution after a match is found"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "network.Input": {
- "properties": {
- "data": {
- "type": "string",
- "title": "data to send as input",
- "description": "Data is the data to send as the input"
- },
- "type": {
- "enum": [
- "hex",
- "text"
- ],
- "type": "string",
- "title": "type is the type of input data",
- "description": "Type of input specified in data field"
- },
- "read": {
- "type": "integer",
- "title": "bytes to read from socket",
- "description": "Number of bytes to read from socket"
- },
- "name": {
- "type": "string",
- "title": "optional name for data read",
- "description": "Optional name of the data read to provide matching on"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "network.Request": {
- "properties": {
- "id": {
- "type": "string",
- "title": "id of the request",
- "description": "ID of the network request"
- },
- "host": {
- "items": {
- "type": "string"
- },
- "type": "array",
- "title": "host to send requests to",
- "description": "Host to send network requests to"
- },
- "attack": {
- "enum": [
- "sniper",
- "pitchfork",
- "clusterbomb"
- ],
- "type": "string",
- "title": "attack is the payload combination",
- "description": "Attack is the type of payload combinations to perform"
- },
- "payloads": {
- "patternProperties": {
- ".*": {
- "additionalProperties": true
- }
- },
- "type": "object",
- "title": "payloads for the network request",
- "description": "Payloads contains any payloads for the current request"
- },
- "inputs": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/network.Input"
- },
- "type": "array",
- "title": "inputs for the network request",
- "description": "Inputs contains any input/output for the current request"
- },
- "read-size": {
- "type": "integer",
- "title": "size of network response to read",
- "description": "Size of response to read at the end. Default is 1024 bytes"
- },
- "matchers": {
- "items": {
- "$ref": "#/definitions/matchers.Matcher"
- },
- "type": "array",
- "title": "matchers to run on response",
- "description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
- },
- "extractors": {
- "items": {
- "$ref": "#/definitions/extractors.Extractor"
- },
- "type": "array",
- "title": "extractors to run on response",
- "description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
- },
- "matchers-condition": {
- "enum": [
- "and",
- "or"
- ],
- "type": "string",
- "title": "condition between the matchers",
- "description": "Conditions between the matchers"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "templates.Template": {
- "required": [
- "id",
- "info"
- ],
- "properties": {
- "id": {
- "type": "string",
- "title": "id of the template",
- "description": "The Unique ID for the template",
- "examples": [
- "cve-2021-19520"
- ]
- },
- "info": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/model.Info",
- "title": "info for the template",
- "description": "Info contains metadata for the template"
- },
- "requests": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/http.Request"
- },
- "type": "array",
- "title": "http requests to make",
- "description": "HTTP requests to make for the template"
- },
- "dns": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/dns.Request"
- },
- "type": "array",
- "title": "dns requests to make",
- "description": "DNS requests to make for the template"
- },
- "file": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/file.Request"
- },
- "type": "array",
- "title": "file requests to make",
- "description": "File requests to make for the template"
- },
- "network": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/network.Request"
- },
- "type": "array",
- "title": "network requests to make",
- "description": "Network requests to make for the template"
- },
- "headless": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/headless.Request"
- },
- "type": "array",
- "title": "headless requests to make",
- "description": "Headless requests to make for the template"
- },
- "workflows": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/workflows.WorkflowTemplate"
- },
- "type": "array",
- "title": "list of workflows to execute",
- "description": "List of workflows to execute for template"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "workflows.Matcher": {
- "properties": {
- "name": {
- "type": "string",
- "title": "name of item to match",
- "description": "Name of item to match"
- },
- "subtemplates": {
- "items": {
- "$ref": "#/definitions/workflows.WorkflowTemplate"
- },
- "type": "array",
- "title": "templates to run after match",
- "description": "Templates to run after match"
- }
- },
- "additionalProperties": false,
- "type": "object"
- },
- "workflows.WorkflowTemplate": {
- "properties": {
- "template": {
- "type": "string",
- "title": "template/directory to execute",
- "description": "Template or directory to execute as part of workflow"
- },
- "tags": {
- "$ref": "#/definitions/model.StringSlice",
- "title": "tags to execute",
- "description": "Tags to run template based on"
- },
- "matchers": {
- "items": {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "$ref": "#/definitions/workflows.Matcher"
- },
- "type": "array",
- "title": "name based template result matchers",
- "description": "Matchers perform name based matching to run subtemplates for a workflow"
- },
- "subtemplates": {
- "items": {
- "$ref": "#/definitions/workflows.WorkflowTemplate"
- },
- "type": "array",
- "title": "subtemplate based result matchers",
- "description": "Subtemplates are ran if the template field Template matches"
- }
- },
- "additionalProperties": false,
- "type": "object"
- }
- }
-}
diff --git a/v2/pkg/model/model.go b/v2/pkg/model/model.go
index 9a1b8c13f..d6834c78e 100644
--- a/v2/pkg/model/model.go
+++ b/v2/pkg/model/model.go
@@ -65,4 +65,41 @@ type Info struct {
// - value: >
// map[string]string{"customField1":"customValue1"}
AdditionalFields map[string]string `json:"additional-fields,omitempty" yaml:"additional-fields,omitempty" jsonschema:"title=additional metadata for the template,description=Additional metadata fields for the template"`
+
+ // description: |
+ // Classification contains classification information about the template.
+ Classification *Classification `json:"classification,omitempty" yaml:"classification,omitempty" jsonschema:"title=classification info for the template,description=Classification information for the template"`
+
+ // description: |
+ // Remediation steps for the template.
+ //
+ // You can go in-depth here on how to mitigate the problem found by this template.
+ //
+ // examples:
+ // - value: "\"Change the default administrative username and password of Apache ActiveMQ by editing the file jetty-realm.properties\""
+ Remediation string `json:"remediation,omitempty" yaml:"remediation,omitempty" jsonschema:"title=remediation steps for the template,description=In-depth explanation on how to fix the issues found by the template,example=Change the default administrative username and password of Apache ActiveMQ by editing the file jetty-realm.properties"`
+}
+
+// Classification contains the vulnerability classification data for a template.
+type Classification struct {
+ // description: |
+ // CVE ID for the template
+ // examples:
+ // - value: "\"CVE-2020-14420\""
+ CVEID stringslice.StringSlice `json:"cve-id,omitempty" yaml:"cve-id,omitempty" jsonschema:"title=cve ids for the template,description=CVE IDs for the template,example=CVE-2020-14420"`
+ // description: |
+ // CWE ID for the template.
+ // examples:
+ // - value: "\"CWE-22\""
+ CWEID stringslice.StringSlice `json:"cwe-id,omitempty" yaml:"cwe-id,omitempty" jsonschema:"title=cwe ids for the template,description=CWE IDs for the template,example=CWE-22"`
+ // description: |
+ // CVSS Metrics for the template.
+ // examples:
+ // - value: "\"3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\""
+ CVSSMetrics string `json:"cvss-metrics,omitempty" yaml:"cvss-metrics,omitempty" jsonschema:"title=cvss metrics for the template,description=CVSS Metrics for the template,example=3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"`
+ // description: |
+ // CVSS Score for the template.
+ // examples:
+ // - value: "\"9.8\""
+ CVSSScore float64 `json:"cvss-score,omitempty" yaml:"cvss-score,omitempty" jsonschema:"title=cvss score for the template,description=CVSS Score for the template,example=9.8"`
}
diff --git a/v2/pkg/output/format_json.go b/v2/pkg/output/format_json.go
index 814bab1fd..29fd41e0e 100644
--- a/v2/pkg/output/format_json.go
+++ b/v2/pkg/output/format_json.go
@@ -6,5 +6,9 @@ import (
// formatJSON formats the output for json based formatting
func (w *StandardWriter) formatJSON(output *ResultEvent) ([]byte, error) {
+ if !w.jsonReqResp { // don't show request-response in json if not asked
+ output.Request = ""
+ output.Response = ""
+ }
return jsoniter.Marshal(output)
}
diff --git a/v2/pkg/output/output.go b/v2/pkg/output/output.go
index 4f9ecbd0c..8f42646cf 100644
--- a/v2/pkg/output/output.go
+++ b/v2/pkg/output/output.go
@@ -33,6 +33,7 @@ type Writer interface {
// StandardWriter is a writer writing output to file and screen for results.
type StandardWriter struct {
json bool
+ jsonReqResp bool
noTimestamp bool
noMetadata bool
aurora aurora.Aurora
@@ -94,7 +95,7 @@ type ResultEvent struct {
}
// NewStandardWriter creates a new output writer based on user configurations
-func NewStandardWriter(colors, noMetadata, noTimestamp, json bool, file, traceFile string) (*StandardWriter, error) {
+func NewStandardWriter(colors, noMetadata, noTimestamp, json, jsonReqResp bool, file, traceFile string) (*StandardWriter, error) {
auroraColorizer := aurora.NewAurora(colors)
var outputFile *fileWriter
@@ -115,6 +116,7 @@ func NewStandardWriter(colors, noMetadata, noTimestamp, json bool, file, traceFi
}
writer := &StandardWriter{
json: json,
+ jsonReqResp: jsonReqResp,
noMetadata: noMetadata,
noTimestamp: noTimestamp,
aurora: auroraColorizer,
diff --git a/v2/pkg/protocols/common/interactsh/interactsh.go b/v2/pkg/protocols/common/interactsh/interactsh.go
index 659e68092..c1435b2cd 100644
--- a/v2/pkg/protocols/common/interactsh/interactsh.go
+++ b/v2/pkg/protocols/common/interactsh/interactsh.go
@@ -6,6 +6,7 @@ import (
"net/url"
"os"
"strings"
+ "sync"
"sync/atomic"
"time"
@@ -36,8 +37,9 @@ type Client struct {
pollDuration time.Duration
cooldownDuration time.Duration
- generated uint32 // decide to wait if we have a generated url
- matched bool
+ firstTimeGroup sync.Once
+ generated uint32 // decide to wait if we have a generated url
+ matched bool
}
var (
@@ -81,14 +83,6 @@ func New(options *Options) (*Client, error) {
return nil, errors.Wrap(err, "could not parse server url")
}
- interactsh, err := client.New(&client.Options{
- ServerURL: options.ServerURL,
- Token: options.Authorization,
- PersistentSession: false,
- })
- if err != nil {
- return nil, errors.Wrap(err, "could not create client")
- }
configure := ccache.Configure()
configure = configure.MaxSize(options.CacheSize)
cache := ccache.New(configure)
@@ -98,7 +92,6 @@ func New(options *Options) (*Client, error) {
interactionsCache := ccache.New(interactionsCfg)
interactClient := &Client{
- interactsh: interactsh,
eviction: options.Eviction,
interactions: interactionsCache,
dotHostname: "." + parsed.Host,
@@ -107,21 +100,34 @@ func New(options *Options) (*Client, error) {
pollDuration: options.PollDuration,
cooldownDuration: options.ColldownPeriod,
}
+ return interactClient, nil
+}
- interactClient.interactsh.StartPolling(interactClient.pollDuration, func(interaction *server.Interaction) {
- if options.Debug {
+func (c *Client) firstTimeInitializeClient() error {
+ interactsh, err := client.New(&client.Options{
+ ServerURL: c.options.ServerURL,
+ Token: c.options.Authorization,
+ PersistentSession: false,
+ })
+ if err != nil {
+ return errors.Wrap(err, "could not create client")
+ }
+ c.interactsh = interactsh
+
+ interactsh.StartPolling(c.pollDuration, func(interaction *server.Interaction) {
+ if c.options.Debug {
debugPrintInteraction(interaction)
}
- item := interactClient.requests.Get(interaction.UniqueID)
+ item := c.requests.Get(interaction.UniqueID)
if item == nil {
// If we don't have any request for this ID, add it to temporary
// lru cache, so we can correlate when we get an add request.
- gotItem := interactClient.interactions.Get(interaction.UniqueID)
+ gotItem := c.interactions.Get(interaction.UniqueID)
if gotItem == nil {
- interactClient.interactions.Set(interaction.UniqueID, []*server.Interaction{interaction}, defaultInteractionDuration)
+ c.interactions.Set(interaction.UniqueID, []*server.Interaction{interaction}, defaultInteractionDuration)
} else if items, ok := gotItem.Value().([]*server.Interaction); ok {
items = append(items, interaction)
- interactClient.interactions.Set(interaction.UniqueID, items, defaultInteractionDuration)
+ c.interactions.Set(interaction.UniqueID, items, defaultInteractionDuration)
}
return
}
@@ -129,9 +135,9 @@ func New(options *Options) (*Client, error) {
if !ok {
return
}
- _ = interactClient.processInteractionForRequest(interaction, request)
+ _ = c.processInteractionForRequest(interaction, request)
})
- return interactClient, nil
+ return nil
}
// processInteractionForRequest processes an interaction for a request
@@ -171,6 +177,11 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
// URL returns a new URL that can be interacted with
func (c *Client) URL() string {
+ c.firstTimeGroup.Do(func() {
+ if err := c.firstTimeInitializeClient(); err != nil {
+ gologger.Error().Msgf("Could not initialize interactsh client: %s", err)
+ }
+ })
atomic.CompareAndSwapUint32(&c.generated, 0, 1)
return c.interactsh.URL()
}
@@ -180,8 +191,10 @@ func (c *Client) Close() bool {
if c.cooldownDuration > 0 && atomic.LoadUint32(&c.generated) == 1 {
time.Sleep(c.cooldownDuration)
}
- c.interactsh.StopPolling()
- c.interactsh.Close()
+ if c.interactsh != nil {
+ c.interactsh.StopPolling()
+ c.interactsh.Close()
+ }
return c.matched
}
diff --git a/v2/pkg/protocols/dns/operators.go b/v2/pkg/protocols/dns/operators.go
index 49fb3732a..5e5137420 100644
--- a/v2/pkg/protocols/dns/operators.go
+++ b/v2/pkg/protocols/dns/operators.go
@@ -147,10 +147,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
Matched: types.ToString(wrapped.InternalEvent["matched"]),
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
Timestamp: time.Now(),
- }
- if r.options.Options.JSONRequests {
- data.Request = types.ToString(wrapped.InternalEvent["request"])
- data.Response = types.ToString(wrapped.InternalEvent["raw"])
+ Request: types.ToString(wrapped.InternalEvent["request"]),
+ Response: types.ToString(wrapped.InternalEvent["raw"]),
}
return data
}
diff --git a/v2/pkg/protocols/file/operators.go b/v2/pkg/protocols/file/operators.go
index c56147763..6631aeba1 100644
--- a/v2/pkg/protocols/file/operators.go
+++ b/v2/pkg/protocols/file/operators.go
@@ -143,10 +143,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
Matched: types.ToString(wrapped.InternalEvent["matched"]),
Host: types.ToString(wrapped.InternalEvent["matched"]),
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
+ Response: types.ToString(wrapped.InternalEvent["raw"]),
Timestamp: time.Now(),
}
- if r.options.Options.JSONRequests {
- data.Response = types.ToString(wrapped.InternalEvent["raw"])
- }
return data
}
diff --git a/v2/pkg/protocols/headless/operators.go b/v2/pkg/protocols/headless/operators.go
index e3c5dff41..776adb89c 100644
--- a/v2/pkg/protocols/headless/operators.go
+++ b/v2/pkg/protocols/headless/operators.go
@@ -116,10 +116,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
Timestamp: time.Now(),
IP: types.ToString(wrapped.InternalEvent["ip"]),
- }
- if r.options.Options.JSONRequests {
- data.Request = types.ToString(wrapped.InternalEvent["request"])
- data.Response = types.ToString(wrapped.InternalEvent["data"])
+ Request: types.ToString(wrapped.InternalEvent["request"]),
+ Response: types.ToString(wrapped.InternalEvent["data"]),
}
return data
}
diff --git a/v2/pkg/protocols/http/operators.go b/v2/pkg/protocols/http/operators.go
index 365f62d23..249bf3f3e 100644
--- a/v2/pkg/protocols/http/operators.go
+++ b/v2/pkg/protocols/http/operators.go
@@ -154,10 +154,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
Timestamp: time.Now(),
IP: types.ToString(wrapped.InternalEvent["ip"]),
- }
- if r.options.Options.JSONRequests {
- data.Request = types.ToString(wrapped.InternalEvent["request"])
- data.Response = types.ToString(wrapped.InternalEvent["response"])
+ Request: types.ToString(wrapped.InternalEvent["request"]),
+ Response: types.ToString(wrapped.InternalEvent["response"]),
}
return data
}
diff --git a/v2/pkg/protocols/network/operators.go b/v2/pkg/protocols/network/operators.go
index aa8e5e11a..81b5fcffe 100644
--- a/v2/pkg/protocols/network/operators.go
+++ b/v2/pkg/protocols/network/operators.go
@@ -118,10 +118,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
Metadata: wrapped.OperatorsResult.PayloadValues,
Timestamp: time.Now(),
IP: types.ToString(wrapped.InternalEvent["ip"]),
- }
- if r.options.Options.JSONRequests {
- data.Request = types.ToString(wrapped.InternalEvent["request"])
- data.Response = types.ToString(wrapped.InternalEvent["data"])
+ Request: types.ToString(wrapped.InternalEvent["request"]),
+ Response: types.ToString(wrapped.InternalEvent["data"]),
}
return data
}
diff --git a/v2/pkg/protocols/offlinehttp/operators.go b/v2/pkg/protocols/offlinehttp/operators.go
index 351c3a066..8aaf0663e 100644
--- a/v2/pkg/protocols/offlinehttp/operators.go
+++ b/v2/pkg/protocols/offlinehttp/operators.go
@@ -145,10 +145,8 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out
Metadata: wrapped.OperatorsResult.PayloadValues,
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
IP: types.ToString(wrapped.InternalEvent["ip"]),
- }
- if r.options.Options.JSONRequests {
- data.Request = types.ToString(wrapped.InternalEvent["request"])
- data.Response = types.ToString(wrapped.InternalEvent["raw"])
+ Request: types.ToString(wrapped.InternalEvent["request"]),
+ Response: types.ToString(wrapped.InternalEvent["raw"]),
}
return data
}
diff --git a/v2/pkg/reporting/format/format.go b/v2/pkg/reporting/format/format.go
index a90130020..88492d2d3 100644
--- a/v2/pkg/reporting/format/format.go
+++ b/v2/pkg/reporting/format/format.go
@@ -3,9 +3,12 @@ package format
import (
"bytes"
"fmt"
- "github.com/projectdiscovery/nuclei/v2/pkg/utils"
+ "strconv"
"strings"
+ "github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
+ "github.com/projectdiscovery/nuclei/v2/pkg/utils"
+
"github.com/projectdiscovery/nuclei/v2/pkg/model"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
@@ -16,13 +19,10 @@ func Summary(event *output.ResultEvent) string {
template := GetMatchedTemplate(event)
builder := &strings.Builder{}
- builder.WriteString("[")
- builder.WriteString(template)
- builder.WriteString("] [")
- builder.WriteString(types.ToString(event.Info.SeverityHolder))
- builder.WriteString("] ")
builder.WriteString(types.ToString(event.Info.Name))
- builder.WriteString(" found on ")
+ builder.WriteString(" (")
+ builder.WriteString(template)
+ builder.WriteString(") found on ")
builder.WriteString(event.Host)
data := builder.String()
return data
@@ -71,6 +71,7 @@ func MarkdownDescription(event *output.ResultEvent) string { // TODO remove the
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 {
builder.WriteString("\n**Extra Information**\n\n")
+
if len(event.ExtractedResults) > 0 {
builder.WriteString("**Extracted results**:\n\n")
for _, v := range event.ExtractedResults {
@@ -131,7 +132,7 @@ func MarkdownDescription(event *output.ResultEvent) string { // TODO remove the
}
}
- builder.WriteString("\n---\nGenerated by [Nuclei](https://github.com/projectdiscovery/nuclei)")
+ builder.WriteString(fmt.Sprintf("\n---\nGenerated by [Nuclei %s](https://github.com/projectdiscovery/nuclei)", config.Version))
data := builder.String()
return data
}
@@ -159,6 +160,16 @@ func ToMarkdownTableString(templateInfo *model.Info) string {
fields.Set("Tags", templateInfo.Tags.String())
fields.Set("Severity", templateInfo.SeverityHolder.Severity.String())
fields.Set("Description", templateInfo.Description)
+ fields.Set("Remediation", templateInfo.Remediation)
+
+ classification := templateInfo.Classification
+ if classification != nil {
+ if classification.CVSSMetrics != "" {
+ generateCVSSMetricsFromClassification(classification, fields)
+ }
+ generateCVECWEIDLinksFromClassification(classification, fields)
+ fields.Set("CVSS-Score", strconv.FormatFloat(classification.CVSSScore, 'f', 2, 64))
+ }
builder := &bytes.Buffer{}
@@ -175,3 +186,44 @@ func ToMarkdownTableString(templateInfo *model.Info) string {
return builder.String()
}
+
+func generateCVSSMetricsFromClassification(classification *model.Classification, fields *utils.InsertionOrderedStringMap) {
+ // Generate cvss link
+ var cvssLinkPrefix string
+ if strings.Contains(classification.CVSSMetrics, "CVSS:3.0") {
+ cvssLinkPrefix = "https://www.first.org/cvss/calculator/3.0#"
+ } else if strings.Contains(classification.CVSSMetrics, "CVSS:3.1") {
+ cvssLinkPrefix = "https://www.first.org/cvss/calculator/3.1#"
+ }
+ if cvssLinkPrefix != "" {
+ fields.Set("CVSS-Metrics", fmt.Sprintf("[%s](%s%s)", classification.CVSSMetrics, cvssLinkPrefix, classification.CVSSMetrics))
+ } else {
+ fields.Set("CVSS-Metrics", classification.CVSSMetrics)
+ }
+}
+
+func generateCVECWEIDLinksFromClassification(classification *model.Classification, fields *utils.InsertionOrderedStringMap) {
+ cwes := classification.CWEID.ToSlice()
+
+ cweIDs := make([]string, 0, len(cwes))
+ for _, value := range cwes {
+ parts := strings.Split(value, "-")
+ if len(parts) != 2 {
+ continue
+ }
+ cweIDs = append(cweIDs, fmt.Sprintf("[%s](https://cwe.mitre.org/data/definitions/%s.html)", strings.ToUpper(value), parts[1]))
+ }
+ if len(cweIDs) > 0 {
+ fields.Set("CWE-ID", strings.Join(cweIDs, ","))
+ }
+
+ cves := classification.CVEID.ToSlice()
+
+ cveIDs := make([]string, 0, len(cves))
+ for _, value := range cves {
+ cveIDs = append(cveIDs, fmt.Sprintf("[%s](https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s)", strings.ToUpper(value), value))
+ }
+ if len(cveIDs) > 0 {
+ fields.Set("CVE-ID", strings.Join(cveIDs, ","))
+ }
+}
diff --git a/v2/pkg/reporting/trackers/jira/jira.go b/v2/pkg/reporting/trackers/jira/jira.go
index a3d50db55..1bfe2edd5 100644
--- a/v2/pkg/reporting/trackers/jira/jira.go
+++ b/v2/pkg/reporting/trackers/jira/jira.go
@@ -8,6 +8,7 @@ import (
"github.com/andygrunwald/go-jira"
"github.com/projectdiscovery/gologger"
+ "github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/format"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
@@ -240,7 +241,7 @@ func jiraFormatDescription(event *output.ResultEvent) string { // TODO remove th
}
}
}
- builder.WriteString("\n---\nGenerated by [Nuclei|https://github.com/projectdiscovery/nuclei]")
+ builder.WriteString(fmt.Sprintf("\n---\nGenerated by [Nuclei v%s](https://github.com/projectdiscovery/nuclei)", config.Version))
data := builder.String()
return data
}
diff --git a/v2/pkg/templates/templates_doc.go b/v2/pkg/templates/templates_doc.go
index dcbc37f5a..553b937ef 100644
--- a/v2/pkg/templates/templates_doc.go
+++ b/v2/pkg/templates/templates_doc.go
@@ -1,4 +1,3 @@
-// Package templates
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -12,8 +11,9 @@ import (
var (
TemplateDoc encoder.Doc
MODELInfoDoc encoder.Doc
- MODELStringSliceDoc encoder.Doc
- SEVERITYSeverityHolderDoc encoder.Doc
+ STRINGSLICEStringSliceDoc encoder.Doc
+ SEVERITYHolderDoc encoder.Doc
+ MODELClassificationDoc encoder.Doc
HTTPRequestDoc encoder.Doc
MATCHERSMatcherDoc encoder.Doc
EXTRACTORSExtractorDoc encoder.Doc
@@ -96,7 +96,7 @@ func init() {
FieldName: "info",
},
}
- MODELInfoDoc.Fields = make([]encoder.Doc, 7)
+ MODELInfoDoc.Fields = make([]encoder.Doc, 9)
MODELInfoDoc.Fields[0].Name = "name"
MODELInfoDoc.Fields[0].Type = "string"
MODELInfoDoc.Fields[0].Note = ""
@@ -107,14 +107,14 @@ func init() {
MODELInfoDoc.Fields[0].AddExample("", "Nagios Default Credentials Check")
MODELInfoDoc.Fields[1].Name = "author"
- MODELInfoDoc.Fields[1].Type = "StringSlice"
+ MODELInfoDoc.Fields[1].Type = "stringslice.StringSlice"
MODELInfoDoc.Fields[1].Note = ""
MODELInfoDoc.Fields[1].Description = "Author of the template.\n\nMultiple values can also be specified separated by commas."
MODELInfoDoc.Fields[1].Comments[encoder.LineComment] = "Author of the template."
MODELInfoDoc.Fields[1].AddExample("", "
")
MODELInfoDoc.Fields[2].Name = "tags"
- MODELInfoDoc.Fields[2].Type = "StringSlice"
+ MODELInfoDoc.Fields[2].Type = "stringslice.StringSlice"
MODELInfoDoc.Fields[2].Note = ""
MODELInfoDoc.Fields[2].Description = "Any tags for the template.\n\nMultiple values can also be specified separated by commas."
MODELInfoDoc.Fields[2].Comments[encoder.LineComment] = "Any tags for the template."
@@ -130,14 +130,14 @@ func init() {
MODELInfoDoc.Fields[3].AddExample("", "Subversion ALM for the enterprise before 8.8.2 allows reflected XSS at multiple locations")
MODELInfoDoc.Fields[4].Name = "reference"
- MODELInfoDoc.Fields[4].Type = "StringSlice"
+ MODELInfoDoc.Fields[4].Type = "stringslice.StringSlice"
MODELInfoDoc.Fields[4].Note = ""
MODELInfoDoc.Fields[4].Description = "References for the template.\n\nThis should contain links relevant to the template."
MODELInfoDoc.Fields[4].Comments[encoder.LineComment] = "References for the template."
MODELInfoDoc.Fields[4].AddExample("", []string{"https://github.com/strapi/strapi", "https://github.com/getgrav/grav"})
MODELInfoDoc.Fields[5].Name = "severity"
- MODELInfoDoc.Fields[5].Type = "severity.SeverityHolder"
+ MODELInfoDoc.Fields[5].Type = "severity.Holder"
MODELInfoDoc.Fields[5].Note = ""
MODELInfoDoc.Fields[5].Description = "Severity of the template."
MODELInfoDoc.Fields[5].Comments[encoder.LineComment] = "Severity of the template."
@@ -155,28 +155,109 @@ func init() {
MODELInfoDoc.Fields[6].Comments[encoder.LineComment] = "AdditionalFields regarding metadata of the template."
MODELInfoDoc.Fields[6].AddExample("", map[string]string{"customField1": "customValue1"})
+ MODELInfoDoc.Fields[7].Name = "classification"
+ MODELInfoDoc.Fields[7].Type = "model.Classification"
+ MODELInfoDoc.Fields[7].Note = ""
+ MODELInfoDoc.Fields[7].Description = "Classification contains classification information about the template."
+ MODELInfoDoc.Fields[7].Comments[encoder.LineComment] = "Classification contains classification information about the template."
+ MODELInfoDoc.Fields[8].Name = "remediation"
+ MODELInfoDoc.Fields[8].Type = "string"
+ MODELInfoDoc.Fields[8].Note = ""
+ MODELInfoDoc.Fields[8].Description = "Remediation steps for the template.\n\nYou can go in-depth here on how to mitigate the problem found by this template."
+ MODELInfoDoc.Fields[8].Comments[encoder.LineComment] = "Remediation steps for the template."
- MODELStringSliceDoc.Type = "model.StringSlice"
- MODELStringSliceDoc.Comments[encoder.LineComment] = ""
- MODELStringSliceDoc.Description = ""
- MODELStringSliceDoc.AppearsIn = []encoder.Appearance{
+ MODELInfoDoc.Fields[8].AddExample("", "Change the default administrative username and password of Apache ActiveMQ by editing the file jetty-realm.properties")
+
+ STRINGSLICEStringSliceDoc.Type = "stringslice.StringSlice"
+ STRINGSLICEStringSliceDoc.Comments[encoder.LineComment] = " StringSlice represents a single (in-lined) or multiple string value(s)."
+ STRINGSLICEStringSliceDoc.Description = "StringSlice represents a single (in-lined) or multiple string value(s).\n The unmarshaller does not automatically convert in-lined strings to []string, hence the interface{} type is required."
+
+ STRINGSLICEStringSliceDoc.AddExample("", "")
+
+ STRINGSLICEStringSliceDoc.AddExample("Example tags", "cve,cve2019,grafana,auth-bypass,dos")
+
+ STRINGSLICEStringSliceDoc.AddExample("", []string{"https://github.com/strapi/strapi", "https://github.com/getgrav/grav"})
+
+ STRINGSLICEStringSliceDoc.AddExample("", "CVE-2020-14420")
+
+ STRINGSLICEStringSliceDoc.AddExample("", "CWE-22")
+ STRINGSLICEStringSliceDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "model.Info",
+ FieldName: "author",
+ },
+ {
+ TypeName: "model.Info",
+ FieldName: "tags",
+ },
+ {
+ TypeName: "model.Info",
+ FieldName: "reference",
+ },
+ {
+ TypeName: "model.Classification",
+ FieldName: "cve-id",
+ },
+ {
+ TypeName: "model.Classification",
+ FieldName: "cwe-id",
+ },
{
TypeName: "workflows.WorkflowTemplate",
FieldName: "tags",
},
}
- MODELStringSliceDoc.Fields = make([]encoder.Doc, 0)
+ STRINGSLICEStringSliceDoc.Fields = make([]encoder.Doc, 0)
- SEVERITYSeverityHolderDoc.Type = "severity.SeverityHolder"
- SEVERITYSeverityHolderDoc.Comments[encoder.LineComment] = ""
- SEVERITYSeverityHolderDoc.Description = ""
- SEVERITYSeverityHolderDoc.AppearsIn = []encoder.Appearance{
+ SEVERITYHolderDoc.Type = "severity.Holder"
+ SEVERITYHolderDoc.Comments[encoder.LineComment] = " Holder holds a Severity type. Required for un/marshalling purposes"
+ SEVERITYHolderDoc.Description = "Holder holds a Severity type. Required for un/marshalling purposes"
+ SEVERITYHolderDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "model.Info",
FieldName: "severity",
},
}
- SEVERITYSeverityHolderDoc.Fields = make([]encoder.Doc, 0)
+ SEVERITYHolderDoc.Fields = make([]encoder.Doc, 0)
+
+ MODELClassificationDoc.Type = "model.Classification"
+ MODELClassificationDoc.Comments[encoder.LineComment] = ""
+ MODELClassificationDoc.Description = ""
+ MODELClassificationDoc.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "model.Info",
+ FieldName: "classification",
+ },
+ }
+ MODELClassificationDoc.Fields = make([]encoder.Doc, 4)
+ MODELClassificationDoc.Fields[0].Name = "cve-id"
+ MODELClassificationDoc.Fields[0].Type = "stringslice.StringSlice"
+ MODELClassificationDoc.Fields[0].Note = ""
+ MODELClassificationDoc.Fields[0].Description = "CVE ID for the template"
+ MODELClassificationDoc.Fields[0].Comments[encoder.LineComment] = "CVE ID for the template"
+
+ MODELClassificationDoc.Fields[0].AddExample("", "CVE-2020-14420")
+ MODELClassificationDoc.Fields[1].Name = "cwe-id"
+ MODELClassificationDoc.Fields[1].Type = "stringslice.StringSlice"
+ MODELClassificationDoc.Fields[1].Note = ""
+ MODELClassificationDoc.Fields[1].Description = "CWE ID for the template."
+ MODELClassificationDoc.Fields[1].Comments[encoder.LineComment] = "CWE ID for the template."
+
+ MODELClassificationDoc.Fields[1].AddExample("", "CWE-22")
+ MODELClassificationDoc.Fields[2].Name = "cvss-metrics"
+ MODELClassificationDoc.Fields[2].Type = "string"
+ MODELClassificationDoc.Fields[2].Note = ""
+ MODELClassificationDoc.Fields[2].Description = "CVSS Metrics for the template."
+ MODELClassificationDoc.Fields[2].Comments[encoder.LineComment] = "CVSS Metrics for the template."
+
+ MODELClassificationDoc.Fields[2].AddExample("", "3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H")
+ MODELClassificationDoc.Fields[3].Name = "cvss-score"
+ MODELClassificationDoc.Fields[3].Type = "float64"
+ MODELClassificationDoc.Fields[3].Note = ""
+ MODELClassificationDoc.Fields[3].Description = "CVSS Score for the template."
+ MODELClassificationDoc.Fields[3].Comments[encoder.LineComment] = "CVSS Score for the template."
+
+ MODELClassificationDoc.Fields[3].AddExample("", "9.8")
HTTPRequestDoc.Type = "http.Request"
HTTPRequestDoc.Comments[encoder.LineComment] = " Request contains a http request to be made from a template"
@@ -971,7 +1052,7 @@ func init() {
WORKFLOWSWorkflowTemplateDoc.Fields[0].AddExample("A template directory", "misconfigurations/aem")
WORKFLOWSWorkflowTemplateDoc.Fields[1].Name = "tags"
- WORKFLOWSWorkflowTemplateDoc.Fields[1].Type = "model.StringSlice"
+ WORKFLOWSWorkflowTemplateDoc.Fields[1].Type = "stringslice.StringSlice"
WORKFLOWSWorkflowTemplateDoc.Fields[1].Note = ""
WORKFLOWSWorkflowTemplateDoc.Fields[1].Description = "Tags to run templates based on."
WORKFLOWSWorkflowTemplateDoc.Fields[1].Comments[encoder.LineComment] = "Tags to run templates based on."
@@ -1016,8 +1097,9 @@ func GetTemplateDoc() *encoder.FileDoc {
Structs: []*encoder.Doc{
&TemplateDoc,
&MODELInfoDoc,
- &MODELStringSliceDoc,
- &SEVERITYSeverityHolderDoc,
+ &STRINGSLICEStringSliceDoc,
+ &SEVERITYHolderDoc,
+ &MODELClassificationDoc,
&HTTPRequestDoc,
&MATCHERSMatcherDoc,
&EXTRACTORSExtractorDoc,
diff --git a/v2/syntax-reference.md b/v2/syntax-reference.md
deleted file mode 100755
index 006885fb9..000000000
--- a/v2/syntax-reference.md
+++ /dev/null
@@ -1,2701 +0,0 @@
-
-
-
-
-## Template
-Template is a YAML input file which defines all the requests and
- other metadata for a template.
-
-
-
-
-
-
-
-
-id string
-
-
-
-
-ID is the unique id for the template. IDs must be lowercase
-and must not contain spaces in it.
-
-#### Good IDs
-
-A good ID uniquely 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:
-
-
-```yaml
-# ID Example
-id: cve-2021-19520
-```
-
-
-
-
-
-
-
-
-
-Info contains metadata information about the template.
-
-
-
-Examples:
-
-
-```yaml
-info:
- name: Argument Injection in Ruby Dragonfly
- author: 0xspara
- tags: cve,cve2021,rce,ruby
- reference: https://zxsecurity.co.nz/research/argunment-injection-ruby-dragonfly/
- severity: high
-```
-
-
-
-
-
-
-
-
-
-Requests contains the http request to make in the template.
-
-
-
-Examples:
-
-
-```yaml
-requests:
- matchers:
- - type: word
- words:
- - '[core]'
- - type: dsl
- condition: and
- dsl:
- - '!contains(tolower(body), ''
-
-
-
-
-
-
-DNS contains the dns request to make in the template
-
-
-
-Examples:
-
-
-```yaml
-dns:
- extractors:
- - type: regex
- regex:
- - ec2-[-\d]+\.compute[-\d]*\.amazonaws\.com
- - ec2-[-\d]+\.[\w\d\-]+\.compute[-\d]*\.amazonaws\.com
- name: '{{FQDN}}'
- type: CNAME
- class: inet
- retries: 2
- recursion: true
-```
-
-
-
-
-
-
-
-
-
-File contains the file request to make in the template
-
-
-
-Examples:
-
-
-```yaml
-file:
- extractors:
- - type: regex
- regex:
- - amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
- extensions:
- - all
-```
-
-
-
-
-
-
-
-
-
-Network contains the network request to make in the template
-
-
-
-Examples:
-
-
-```yaml
-network:
- host:
- - '{{Hostname}}'
- - '{{Hostname}}:2181'
- inputs:
- - data: "envi\r\nquit\r\n"
- read-size: 2048
- matchers:
- - type: word
- words:
- - zookeeper.version
-```
-
-
-
-
-
-
-
-
-
-Headless contains the headless request to make in the template.
-
-
-
-
-
-
-
-
-Workflows is a list of workflows to execute for a template.
-
-
-
-
-
-
-
-
-
-## model.Info
-Info contains metadata information about a template
-
-Appears in:
-
-
--
Template.info
-
-
-```yaml
-name: Argument Injection in Ruby Dragonfly
-author: 0xspara
-tags: cve,cve2021,rce,ruby
-reference: https://zxsecurity.co.nz/research/argunment-injection-ruby-dragonfly/
-severity: high
-```
-
-
-
-
-
-name string
-
-
-
-
-Name should be good short summary that identifies what the template does.
-
-
-
-Examples:
-
-
-```yaml
-name: bower.json file disclosure
-```
-
-```yaml
-name: Nagios Default Credentials Check
-```
-
-
-
-
-
-
-
-
-author StringSlice
-
-
-
-
-Author of the template.
-
-Multiple values can also be specified separated by commas.
-
-
-
-Examples:
-
-
-```yaml
-author:
-```
-
-
-
-
-
-
-
-
-tags StringSlice
-
-
-
-
-Any tags for the template.
-
-Multiple values can also be specified separated by commas.
-
-
-
-Examples:
-
-
-```yaml
-# Example tags
-tags: cve,cve2019,grafana,auth-bypass,dos
-```
-
-
-
-
-
-
-
-
-description string
-
-
-
-
-Description of the template.
-
-You can go in-depth here on what the template actually does.
-
-
-
-Examples:
-
-
-```yaml
-description: Bower is a package manager which stores packages informations in bower.json file
-```
-
-```yaml
-description: Subversion ALM for the enterprise before 8.8.2 allows reflected XSS at multiple locations
-```
-
-
-
-
-
-
-
-
-reference StringSlice
-
-
-
-
-References for the template.
-
-This should contain links relevant to the template.
-
-
-
-Examples:
-
-
-```yaml
-reference:
- - https://github.com/strapi/strapi
- - https://github.com/getgrav/grav
-```
-
-
-
-
-
-
-
-
-
-Severity of the template.
-
-
-Valid values:
-
-
- - info
-
- - low
-
- - medium
-
- - high
-
- - critical
-
-
-
-
-
-
-additional-fields map[string]string
-
-
-
-
-AdditionalFields regarding metadata of the template.
-
-
-
-Examples:
-
-
-```yaml
-additional-fields:
- customField1: customValue1
-```
-
-
-
-
-
-
-
-
-
-
-## model.StringSlice
-
-Appears in:
-
-
--
workflows.WorkflowTemplate.tags
-
-
-
-
-
-## severity.SeverityHolder
-
-Appears in:
-
-
--
model.Info.severity
-
-
-
-
-
-## http.Request
-Request contains a http request to be made from a template
-
-Appears in:
-
-
--
Template.requests
-
-
-```yaml
-matchers:
- - type: word
- words:
- - '[core]'
- - type: dsl
- condition: and
- dsl:
- - '!contains(tolower(body), ''
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Extractors contains the extraction mechanism for the request to identify
-and extract parts of the response.
-
-
-
-
-
-
-
-matchers-condition string
-
-
-
-
-MatchersCondition is the condition between the matchers. Default is OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-path []string
-
-
-
-
-Path contains the path/s for the HTTP requests. It supports variables
-as placeholders.
-
-
-
-Examples:
-
-
-```yaml
-# Some example path values
-path:
- - '{{BaseURL}}'
- - '{{BaseURL}}/+CSCOU+/../+CSCOE+/files/file_list.json?path=/sessions'
-```
-
-
-
-
-
-
-
-
-raw []string
-
-
-
-
-Raw contains HTTP Requests in Raw format.
-
-
-
-Examples:
-
-
-```yaml
-# Some example raw requests
-raw:
- - |-
- GET /etc/passwd HTTP/1.1
- Host:
- Content-Length: 4
- - |-
- POST /.%0d./.%0d./.%0d./.%0d./bin/sh HTTP/1.1
- Host: {{Hostname}}
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0
- Content-Length: 1
- Connection: close
-
- echo
- echo
- cat /etc/passwd 2>&1
-```
-
-
-
-
-
-
-
-
-id string
-
-
-
-
-ID is the the optional id of the request
-
-
-
-
-
-
-
-name string
-
-
-
-
-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.
-
-
-
-
-
-
-
-attack string
-
-
-
-
-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.
-
-
-Valid values:
-
-
- - sniper
-
- - pitchfork
-
- - clusterbomb
-
-
-
-
-
-
-method string
-
-
-
-
-Method is the HTTP Request Method.
-
-
-Valid values:
-
-
- - GET
-
- - HEAD
-
- - POST
-
- - PUT
-
- - DELETE
-
- - CONNECT
-
- - OPTIONS
-
- - TRACE
-
- - PATCH
-
-
-
-
-
-
-body string
-
-
-
-
-Body is an optional parameter which contains HTTP Request body.
-
-
-
-Examples:
-
-
-```yaml
-# Same Body for a Login POST request
-body: username=test&password=test
-```
-
-
-
-
-
-
-
-
-payloads map[string]interface{}
-
-
-
-
-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.
-
-
-
-
-
-
-
-headers map[string]string
-
-
-
-
-Headers contains HTTP Headers to send with the request.
-
-
-
-Examples:
-
-
-```yaml
-headers:
- Any-Header: Any-Value
- Content-Length: "1"
- Content-Type: application/x-www-form-urlencoded
-```
-
-
-
-
-
-
-
-
-race_count int
-
-
-
-
-RaceCount is the number of times to send a request in Race Condition Attack.
-
-
-
-Examples:
-
-
-```yaml
-# Send a request 5 times
-race_count: 5
-```
-
-
-
-
-
-
-
-
-max-redirects int
-
-
-
-
-MaxRedirects is the maximum number of redirects that should be followed.
-
-
-
-Examples:
-
-
-```yaml
-# Follow upto 5 redirects
-max-redirects: 5
-```
-
-
-
-
-
-
-
-
-pipeline-concurrent-connections int
-
-
-
-
-PipelineConcurrentConnections is number of connections to create during pipelining.
-
-
-
-Examples:
-
-
-```yaml
-# Create 40 concurrent connections
-pipeline-concurrent-connections: 40
-```
-
-
-
-
-
-
-
-
-pipeline-requests-per-connection int
-
-
-
-
-PipelineRequestsPerConnection is number of requests to send per connection when pipelining.
-
-
-
-Examples:
-
-
-```yaml
-# Send 100 requests per pipeline connection
-pipeline-requests-per-connection: 100
-```
-
-
-
-
-
-
-
-
-threads int
-
-
-
-
-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:
-
-
-```yaml
-# Send requests using 10 concurrent threads
-threads: 10
-```
-
-
-
-
-
-
-
-
-max-size int
-
-
-
-
-MaxSize is the maximum size of http response body to read in bytes.
-
-
-
-Examples:
-
-
-```yaml
-# Read max 2048 bytes of the response
-max-size: 2048
-```
-
-
-
-
-
-
-
-
-cookie-reuse bool
-
-
-
-
-CookieReuse is an optional setting that enables cookie reuse for
-all requests defined in raw section.
-
-
-
-
-
-
-
-redirects bool
-
-
-
-
-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.
-
-
-
-
-
-
-
-pipeline bool
-
-
-
-
-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.
-
-
-
-
-
-
-
-unsafe bool
-
-
-
-
-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.
-
-
-
-
-
-
-
-race bool
-
-
-
-
-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.
-
-
-
-
-
-
-
-req-condition bool
-
-
-
-
-ReqCondition automatically assigns numbers to requests and preserves their history.
-
-This allows matching on them later for multi-request conditions.
-
-
-
-
-
-
-
-stop-at-first-match bool
-
-
-
-
-StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
-
-
-
-
-
-
-
-
-
-## matchers.Matcher
-Matcher is used to match a part in the output from a protocol.
-
-Appears in:
-
-
-- http.Request.matchers
-
-- dns.Request.matchers
-
-- file.Request.matchers
-
-- network.Request.matchers
-
-- headless.Request.matchers
-
-
-
-
-
-
-
-type string
-
-
-
-
-Type is the type of the matcher.
-
-
-Valid values:
-
-
- - status
-
- - size
-
- - word
-
- - regex
-
- - binary
-
- - dsl
-
-
-
-
-
-
-condition string
-
-
-
-
-Condition is the optional condition between two matcher variables. By default,
-the condition is assumed to be OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-part string
-
-
-
-
-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:
-
-
-```yaml
-part: body
-```
-
-```yaml
-part: raw
-```
-
-
-
-
-
-
-
-
-negative bool
-
-
-
-
-Negative specifies if the match should be reversed
-It will only match if the condition is not true.
-
-
-
-
-
-
-
-name string
-
-
-
-
-Name of the matcher. Name should be lowercase and must not contain
-spaces or underscores (_).
-
-
-
-Examples:
-
-
-```yaml
-name: cookie-matcher
-```
-
-
-
-
-
-
-
-
-status []int
-
-
-
-
-Status are the acceptable status codes for the response.
-
-
-
-Examples:
-
-
-```yaml
-status:
- - 200
- - 302
-```
-
-
-
-
-
-
-
-
-size []int
-
-
-
-
-Size is the acceptable size for the response
-
-
-
-Examples:
-
-
-```yaml
-size:
- - 3029
- - 2042
-```
-
-
-
-
-
-
-
-
-words []string
-
-
-
-
-Words contains word patterns required to be present in the response part.
-
-
-
-Examples:
-
-
-```yaml
-# Match for outlook mail protection domain
-words:
- - mail.protection.outlook.com
-```
-
-```yaml
-# Match for application/json in response headers
-words:
- - application/json
-```
-
-
-
-
-
-
-
-
-regex []string
-
-
-
-
-Regex contains Regular Expression patterns required to be present in the response part.
-
-
-
-Examples:
-
-
-```yaml
-# Match for Linkerd Service via Regex
-regex:
- - (?mi)^Via\\s*?:.*?linkerd.*$
-```
-
-```yaml
-# Match for Open Redirect via Location header
-regex:
- - (?m)^(?:Location\\s*?:\\s*?)(?:https?://|//)?(?:[a-zA-Z0-9\\-_\\.@]*)example\\.com.*$
-```
-
-
-
-
-
-
-
-
-binary []string
-
-
-
-
-Binary are the binary patterns required to be present in the response part.
-
-
-
-Examples:
-
-
-```yaml
-# Match for Springboot Heapdump Actuator "JAVA PROFILE", "HPROF", "Gunzip magic byte"
-binary:
- - 4a4156412050524f46494c45
- - 4850524f46
- - 1f8b080000000000
-```
-
-```yaml
-# Match for 7zip files
-binary:
- - 377ABCAF271C
-```
-
-
-
-
-
-
-
-
-dsl []string
-
-
-
-
-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:
-
-
-```yaml
-# DSL Matcher for package.json file
-dsl:
- - contains(body, 'packages') && contains(tolower(all_headers), 'application/octet-stream') && status_code == 200
-```
-
-```yaml
-# DSL Matcher for missing strict transport security header
-dsl:
- - '!contains(tolower(all_headers), ''''strict-transport-security'''')'
-```
-
-
-
-
-
-
-
-
-encoding string
-
-
-
-
-Encoding specifies the encoding for the words field if any.
-
-
-Valid values:
-
-
- - hex
-
-
-
-
-
-
-
-
-## extractors.Extractor
-Extractor is used to extract part of response using a regex.
-
-Appears in:
-
-
-- http.Request.extractors
-
-- dns.Request.extractors
-
-- file.Request.extractors
-
-- network.Request.extractors
-
-- headless.Request.extractors
-
-
-
-
-
-
-
-name string
-
-
-
-
-Name of the extractor. Name should be lowercase and must not contain
-spaces or underscores (_).
-
-
-
-Examples:
-
-
-```yaml
-name: cookie-extractor
-```
-
-
-
-
-
-
-
-
-type string
-
-
-
-
-Type is the type of the extractor.
-
-
-Valid values:
-
-
- - regex
-
- - kval
-
- - json
-
- - xpath
-
-
-
-
-
-
-regex []string
-
-
-
-
-Regex contains the regular expression patterns to extract from a part.
-
-Go regex engine does not support lookaheads or lookbehinds, so as a result
-they are also not supported in nuclei.
-
-
-
-Examples:
-
-
-```yaml
-# Braintree Access Token Regex
-regex:
- - access_token\$production\$[0-9a-z]{16}\$[0-9a-f]{32}
-```
-
-```yaml
-# Wordpress Author Extraction regex
-regex:
- - Author:(?:[A-Za-z0-9 -\_="]+)?([A-Za-z0-9]+)<\/span>
-```
-
-
-
-
-
-
-
-
-group int
-
-
-
-
-Group specifies a numbered group to extract from the regex.
-
-
-
-Examples:
-
-
-```yaml
-# Example Regex Group
-group: 1
-```
-
-
-
-
-
-
-
-
-kval []string
-
-
-
-
-description: |
- kval contains the key-value pairs present in the HTTP response header.
- kval extractor can be used to extract HTTP response header and cookie key-value pairs.
- kval extractor inputs are case insensitive, and does not support dash (-) in input which can replaced with underscores (_)
- For example, Content-Type should be replaced with content_type
-
- 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"}
- - name: Extracting value of Content-Type Cookie
- value: >
- []string{"content_type"}
-
-
-
-
-
-
-
-json []string
-
-
-
-
-JSON allows using jq-style syntax to extract items from json response
-
-
-
-Examples:
-
-
-```yaml
-json:
- - .[] | .id
-```
-
-```yaml
-json:
- - .batters | .batter | .[] | .id
-```
-
-
-
-
-
-
-
-
-xpath []string
-
-
-
-
-XPath allows using xpath expressions to extract items from html response
-
-
-
-Examples:
-
-
-```yaml
-xpath:
- - /html/body/div/p[2]/a
-```
-
-
-
-
-
-
-
-
-attribute string
-
-
-
-
-Attribute is an optional attribute to extract from response XPath.
-
-
-
-Examples:
-
-
-```yaml
-attribute: href
-```
-
-
-
-
-
-
-
-
-part string
-
-
-
-
-Part is the part of the request response to extract data from.
-
-Each protocol exposes a lot of different parts which are well
-documented in docs for each request type.
-
-
-
-Examples:
-
-
-```yaml
-part: body
-```
-
-```yaml
-part: raw
-```
-
-
-
-
-
-
-
-
-internal bool
-
-
-
-
-Internal, when set to true will allow using the value extracted
-in the next request for some protocols (like HTTP).
-
-
-
-
-
-
-
-
-
-## dns.Request
-Request contains a DNS protocol request to be made from a template
-
-Appears in:
-
-
-- Template.dns
-
-
-```yaml
-extractors:
- - type: regex
- regex:
- - ec2-[-\d]+\.compute[-\d]*\.amazonaws\.com
- - ec2-[-\d]+\.[\w\d\-]+\.compute[-\d]*\.amazonaws\.com
-name: '{{FQDN}}'
-type: CNAME
-class: inet
-retries: 2
-recursion: true
-```
-
-
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Extractors contains the extraction mechanism for the request to identify
-and extract parts of the response.
-
-
-
-
-
-
-
-matchers-condition string
-
-
-
-
-MatchersCondition is the condition between the matchers. Default is OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-id string
-
-
-
-
-ID is the the optional id of the request
-
-
-
-
-
-
-
-name string
-
-
-
-
-Name is the Hostname to make DNS request for.
-
-Generally, it is set to {{FQDN}} which is the domain we get from input.
-
-
-
-Examples:
-
-
-```yaml
-name: '{{FQDN}}'
-```
-
-
-
-
-
-
-
-
-type string
-
-
-
-
-Type is the type of DNS request to make.
-
-
-Valid values:
-
-
- - A
-
- - NS
-
- - DS
-
- - CNAME
-
- - SOA
-
- - PTR
-
- - MX
-
- - TXT
-
- - AAAA
-
-
-
-
-
-
-class string
-
-
-
-
-Class is the class of the DNS request.
-
-Usually it's enough to just leave it as INET.
-
-
-Valid values:
-
-
- - inet
-
- - csnet
-
- - chaos
-
- - hesiod
-
- - none
-
- - any
-
-
-
-
-
-
-retries int
-
-
-
-
-Retries is the number of retries for the DNS request
-
-
-
-Examples:
-
-
-```yaml
-# Use a retry of 3 to 5 generally
-retries: 5
-```
-
-
-
-
-
-
-
-
-recursion bool
-
-
-
-
-Recursion determines if resolver should recurse all records to get fresh results.
-
-
-
-
-
-
-
-
-
-## file.Request
-Request contains a File matching mechanism for local disk operations.
-
-Appears in:
-
-
-- Template.file
-
-
-```yaml
-extractors:
- - type: regex
- regex:
- - amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
-extensions:
- - all
-```
-
-
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Extractors contains the extraction mechanism for the request to identify
-and extract parts of the response.
-
-
-
-
-
-
-
-matchers-condition string
-
-
-
-
-MatchersCondition is the condition between the matchers. Default is OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-extensions []string
-
-
-
-
-Extensions is the list of extensions to perform matching on.
-
-
-
-Examples:
-
-
-```yaml
-extensions:
- - .txt
- - .go
- - .json
-```
-
-
-
-
-
-
-
-
-denylist []string
-
-
-
-
-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:
-
-
-```yaml
-denylist:
- - .avi
- - .mov
- - .mp3
-```
-
-
-
-
-
-
-
-
-id string
-
-
-
-
-ID is the the optional id of the request
-
-
-
-
-
-
-
-max-size int
-
-
-
-
-MaxSize is the maximum size of the file to run request on.
-
-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:
-
-
-```yaml
-max-size: 2048
-```
-
-
-
-
-
-
-
-
-no-recursive bool
-
-
-
-
-NoRecursive specifies whether to not do recursive checks if folders are provided.
-
-
-
-
-
-
-
-
-
-## network.Request
-Request contains a Network protocol request to be made from a template
-
-Appears in:
-
-
-- Template.network
-
-
-```yaml
-host:
- - '{{Hostname}}'
- - '{{Hostname}}:2181'
-inputs:
- - data: "envi\r\nquit\r\n"
-read-size: 2048
-matchers:
- - type: word
- words:
- - zookeeper.version
-```
-
-
-
-
-
-id string
-
-
-
-
-ID is the the optional id of the request
-
-
-
-
-
-
-
-host []string
-
-
-
-
-Host to send network requests to.
-
-Usually it's set to `{{Hostname}}`. If you want to enable TLS for
-TCP Connection, you can use `tls://{{Hostname}}`.
-
-
-
-Examples:
-
-
-```yaml
-host:
- - '{{Hostname}}'
-```
-
-
-
-
-
-
-
-
-attack string
-
-
-
-
-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.
-
-
-Valid values:
-
-
- - sniper
-
- - pitchfork
-
- - clusterbomb
-
-
-
-
-
-
-payloads map[string]interface{}
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Inputs contains inputs for the network socket
-
-
-
-
-
-
-
-read-size int
-
-
-
-
-ReadSize is the size of response to read at the end
-
-Default value for read-size is 1024.
-
-
-
-Examples:
-
-
-```yaml
-read-size: 2048
-```
-
-
-
-
-
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Extractors contains the extraction mechanism for the request to identify
-and extract parts of the response.
-
-
-
-
-
-
-
-matchers-condition string
-
-
-
-
-MatchersCondition is the condition between the matchers. Default is OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-
-
-## network.Input
-
-Appears in:
-
-
-- network.Request.inputs
-
-
-
-
-
-
-
-data string
-
-
-
-
-Data is the data to send as the input.
-
-It supports DSL Helper Functions as well as normal expressions.
-
-
-
-Examples:
-
-
-```yaml
-data: TEST
-```
-
-```yaml
-data: hex_decode('50494e47')
-```
-
-
-
-
-
-
-
-
-type string
-
-
-
-
-Type is the type of input specified in `data` field.
-
-Default value is text, but hex can be used for hex formatted data.
-
-
-Valid values:
-
-
- - hex
-
- - text
-
-
-
-
-
-
-read int
-
-
-
-
-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:
-
-
-```yaml
-read: 1024
-```
-
-
-
-
-
-
-
-
-name string
-
-
-
-
-Name is the optional name of the data read to provide matching on.
-
-
-
-Examples:
-
-
-```yaml
-name: prefix
-```
-
-
-
-
-
-
-
-
-
-
-## headless.Request
-Request contains a Headless protocol request to be made from a template
-
-Appears in:
-
-
-- Template.headless
-
-
-
-
-
-
-
-id string
-
-
-
-
-ID is the the optional id of the request
-
-
-
-
-
-
-
-
-Steps is the list of actions to run for headless request
-
-
-
-
-
-
-
-
-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.
-
-
-
-
-
-
-
-
-Extractors contains the extraction mechanism for the request to identify
-and extract parts of the response.
-
-
-
-
-
-
-
-matchers-condition string
-
-
-
-
-MatchersCondition is the condition between the matchers. Default is OR.
-
-
-Valid values:
-
-
- - and
-
- - or
-
-
-
-
-
-
-
-
-## engine.Action
-Action is an action taken by the browser to reach a navigation
-
- Each step that the browser executes is an action. Most navigations
- usually start from the ActionLoadURL event, and further navigations
- are discovered on the found page. We also keep track and only
- scrape new navigation from pages we haven't crawled yet.
-
-Appears in:
-
-
-- headless.Request.steps
-
-
-
-
-
-
-
-args map[string]string
-
-
-
-
-Args contain arguments for the headless action.
-Per action arguments are described in detail [here](https://nuclei.projectdiscovery.io/templating-guide/protocols/headless/).
-
-
-
-
-
-
-
-name string
-
-
-
-
-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).
-
-
-
-
-
-
-
-description string
-
-
-
-
-Description is the optional description of the headless action
-
-
-
-
-
-
-
-action string
-
-
-
-
-Action is the type of the action to perform.
-
-
-Valid values:
-
-
- - navigate
-
- - script
-
- - click
-
- - rightclick
-
- - text
-
- - screenshot
-
- - time
-
- - select
-
- - files
-
- - waitload
-
- - getresource
-
- - extract
-
- - setmethod
-
- - addheader
-
- - setheader
-
- - deleteheader
-
- - setbody
-
- - waitevent
-
- - keyboard
-
- - debug
-
- - sleep
-
-
-
-
-
-
-
-
-## workflows.WorkflowTemplate
-
-Appears in:
-
-
-- Template.workflows
-
-- workflows.WorkflowTemplate.subtemplates
-
-- workflows.Matcher.subtemplates
-
-
-
-
-
-
-
-template string
-
-
-
-
-Template is a single template or directory to execute as part of workflow.
-
-
-
-Examples:
-
-
-```yaml
-# A single template
-template: dns/worksites-detection.yaml
-```
-
-```yaml
-# A template directory
-template: misconfigurations/aem
-```
-
-
-
-
-
-
-
-
-
-Tags to run templates based on.
-
-
-
-
-
-
-
-
-Matchers perform name based matching to run subtemplates for a workflow.
-
-
-
-
-
-
-
-
-Subtemplates are ran if the `template` field Template matches.
-
-
-
-
-
-
-
-
-
-## workflows.Matcher
-
-Appears in:
-
-
-- workflows.WorkflowTemplate.matchers
-
-
-
-
-
-
-
-name string
-
-
-
-
-Name is the name of the item to match.
-
-
-
-
-
-
-
-
-Subtemplates are ran if the name of matcher matches.
-
-
-
-
-
-
-
-