@@ -441,18 +441,38 @@ additional-fields:
-## model.StringSlice
+## stringslice.StringSlice
+StringSlice represents a single (in-lined) or multiple string value(s).
+ The unmarshaller does not automatically convert in-lined strings to []string, hence the interface{} type is required.
Appears in:
+-
+```
+```yaml
+# Example tags
+cve,cve2019,grafana,auth-bypass,dos
+```
+```yaml
+- https://github.com/strapi/strapi
+- https://github.com/getgrav/grav
+```
-## severity.SeverityHolder
+## severity.Holder
+Holder holds a Severity type. Required for un/marshalling purposes
Appears in:
@@ -2617,7 +2637,7 @@ template: misconfigurations/aem
diff --git a/nuclei-jsonschema.json b/nuclei-jsonschema.json
index 6092a125..00cb3bc2 100755
--- a/nuclei-jsonschema.json
+++ b/nuclei-jsonschema.json
@@ -2,18 +2,6 @@
"$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": {
@@ -26,12 +14,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 +32,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": {
@@ -66,7 +54,19 @@
"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 +885,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/internal/runner/banner.go b/v2/internal/runner/banner.go
index eed5277d..b75f09c3 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 c5b7c31c..89d7b641 100644
--- a/v2/internal/runner/runner.go
+++ b/v2/internal/runner/runner.go
@@ -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/pkg/protocols/common/interactsh/interactsh.go b/v2/pkg/protocols/common/interactsh/interactsh.go
index da3ef497..3d1ab39b 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"
@@ -35,8 +36,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 (
@@ -80,14 +82,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)
@@ -97,7 +91,6 @@ func New(options *Options) (*Client, error) {
interactionsCache := ccache.New(interactionsCfg)
interactClient := &Client{
- interactsh: interactsh,
eviction: options.Eviction,
interactions: interactionsCache,
dotHostname: "." + parsed.Host,
@@ -106,21 +99,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
}
@@ -128,9 +134,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
@@ -170,6 +176,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()
}
@@ -179,8 +190,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/templates/templates_doc.go b/v2/pkg/templates/templates_doc.go
index dcbc37f5..eb795ae4 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,8 @@ import (
var (
TemplateDoc encoder.Doc
MODELInfoDoc encoder.Doc
- MODELStringSliceDoc encoder.Doc
- SEVERITYSeverityHolderDoc encoder.Doc
+ STRINGSLICEStringSliceDoc encoder.Doc
+ SEVERITYHolderDoc encoder.Doc
HTTPRequestDoc encoder.Doc
MATCHERSMatcherDoc encoder.Doc
EXTRACTORSExtractorDoc encoder.Doc
@@ -107,14 +106,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 +129,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."
@@ -156,27 +155,45 @@ func init() {
MODELInfoDoc.Fields[6].AddExample("", map[string]string{"customField1": "customValue1"})
- MODELStringSliceDoc.Type = "model.StringSlice"
- MODELStringSliceDoc.Comments[encoder.LineComment] = ""
- MODELStringSliceDoc.Description = ""
- MODELStringSliceDoc.AppearsIn = []encoder.Appearance{
+ 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.AppearsIn = []encoder.Appearance{
+ {
+ TypeName: "model.Info",
+ FieldName: "author",
+ },
+ {
+ TypeName: "model.Info",
+ FieldName: "tags",
+ },
+ {
+ TypeName: "model.Info",
+ FieldName: "reference",
+ },
{
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)
HTTPRequestDoc.Type = "http.Request"
HTTPRequestDoc.Comments[encoder.LineComment] = " Request contains a http request to be made from a template"
@@ -971,7 +988,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 +1033,8 @@ func GetTemplateDoc() *encoder.FileDoc {
Structs: []*encoder.Doc{
&TemplateDoc,
&MODELInfoDoc,
- &MODELStringSliceDoc,
- &SEVERITYSeverityHolderDoc,
+ &STRINGSLICEStringSliceDoc,
+ &SEVERITYHolderDoc,
&HTTPRequestDoc,
&MATCHERSMatcherDoc,
&EXTRACTORSExtractorDoc,