Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added JSON format support for templates #3333

Merged
merged 6 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions integration_tests/code/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"id": "go-integration-test",
"info": {
"name": "Basic Go Integration Test",
"author": "pdteam",
"severity": "info"
},
"requests": [
{
"method": "GET",
"path": [
"{{BaseURL}}"
],
"headers": {
"test": "nuclei"
},
"matchers": [
{
"type": "word",
"words": [
"This is test headers matcher text"
]
}
]
}
]
}
1 change: 1 addition & 0 deletions v2/cmd/integration-test/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

var codeTestcases = map[string]testutils.TestCase{
"code/test.yaml": &goIntegrationTest{},
"code/test.json": &goIntegrationTest{},
}

type goIntegrationTest struct{}
Expand Down
1 change: 1 addition & 0 deletions v2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.2
github.com/docker/go-units v0.5.0
github.com/fatih/structs v1.1.0
github.com/go-faker/faker/v4 v4.0.0
github.com/go-git/go-git/v5 v5.5.2
github.com/h2non/filetype v1.1.3
github.com/hashicorp/go-version v1.6.0
Expand Down
2 changes: 2 additions & 0 deletions v2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4x
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-faker/faker/v4 v4.0.0 h1:tfgFaeizVlYGOS1tVo/vcWcKhkNgG1NWm8ibRG0f+aQ=
github.com/go-faker/faker/v4 v4.0.0/go.mod h1:uuNc0PSRxF8nMgjGrrrU4Nw5cF30Jc6Kd0/FUTTYbhg=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/model/types/severity/severity.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (severityHolder *Holder) UnmarshalJSON(data []byte) error {
return nil
}

func (severityHolder *Holder) MarshalJSON() ([]byte, error) {
func (severityHolder Holder) MarshalJSON() ([]byte, error) {
return json.Marshal(severityHolder.Severity.String())
}

Expand Down
14 changes: 14 additions & 0 deletions v2/pkg/model/types/userAgent/user_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ func (userAgentHolder *UserAgentHolder) UnmarshalYAML(unmarshal func(interface{}
return nil
}

func (userAgentHolder *UserAgentHolder) UnmarshalJSON(data []byte) error {
s := strings.Trim(string(data), `"`)
if s == "" {
return nil
}
computedUserAgent, err := toUserAgent(s)
if err != nil {
return err
}

userAgentHolder.Value = computedUserAgent
return nil
}

func (userAgentHolder *UserAgentHolder) MarshalJSON() ([]byte, error) {
return json.Marshal(userAgentHolder.Value.String())
}
Expand Down
14 changes: 14 additions & 0 deletions v2/pkg/operators/extractors/extractor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ func (holder *ExtractorTypeHolder) UnmarshalYAML(unmarshal func(interface{}) err
return nil
}

func (holder *ExtractorTypeHolder) UnmarshalJSON(data []byte) error {
s := strings.Trim(string(data), `"`)
if s == "" {
return nil
}
computedType, err := toExtractorTypes(s)
if err != nil {
return err
}

holder.ExtractorType = computedType
return nil
}

func (holder *ExtractorTypeHolder) MarshalJSON() ([]byte, error) {
return json.Marshal(holder.ExtractorType.String())
}
Expand Down
24 changes: 12 additions & 12 deletions v2/pkg/operators/extractors/extractors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ type Extractor struct {
// spaces or underscores (_).
// examples:
// - value: "\"cookie-extractor\""
Name string `yaml:"name,omitempty" jsonschema:"title=name of the extractor,description=Name of the extractor"`
Name string `yaml:"name,omitempty" json:"name,omitempty" jsonschema:"title=name of the extractor,description=Name of the extractor"`
// description: |
// Type is the type of the extractor.
Type ExtractorTypeHolder `json:"name,omitempty" yaml:"type"`
Type ExtractorTypeHolder `json:"type" yaml:"type"`
// extractorType is the internal type of the extractor
extractorType ExtractorType

Expand All @@ -33,13 +33,13 @@ type Extractor struct {
// - name: Wordpress Author Extraction regex
// value: >
// []string{"Author:(?:[A-Za-z0-9 -\\_=\"]+)?<span(?:[A-Za-z0-9 -\\_=\"]+)?>([A-Za-z0-9]+)<\\/span>"}
Regex []string `yaml:"regex,omitempty" jsonschema:"title=regex to extract from part,description=Regex to extract from part"`
Regex []string `yaml:"regex,omitempty" json:"regex,omitempty" jsonschema:"title=regex to extract from part,description=Regex to extract from part"`
// description: |
// Group specifies a numbered group to extract from the regex.
// examples:
// - name: Example Regex Group
// value: "1"
RegexGroup int `yaml:"group,omitempty" jsonschema:"title=group to extract from regex,description=Group to extract from regex"`
RegexGroup int `yaml:"group,omitempty" json:"group,omitempty" jsonschema:"title=group to extract from regex,description=Group to extract from regex"`
// regexCompiled is the compiled variant
regexCompiled []*regexp.Regexp

Expand All @@ -60,7 +60,7 @@ type Extractor struct {
// - name: Extracting value of Content-Type Cookie
// value: >
// []string{"content_type"}
KVal []string `yaml:"kval,omitempty" jsonschema:"title=kval pairs to extract from response,description=Kval pairs to extract from response"`
KVal []string `yaml:"kval,omitempty" json:"kval,omitempty" jsonschema:"title=kval pairs to extract from response,description=Kval pairs to extract from response"`

// description: |
// JSON allows using jq-style syntax to extract items from json response
Expand All @@ -70,27 +70,27 @@ type Extractor struct {
// []string{".[] | .id"}
// - value: >
// []string{".batters | .batter | .[] | .id"}
JSON []string `yaml:"json,omitempty" jsonschema:"title=json jq expressions to extract data,description=JSON JQ expressions to evaluate from response part"`
JSON []string `yaml:"json,omitempty" json:"json,omitempty" jsonschema:"title=json jq expressions to extract data,description=JSON JQ expressions to evaluate from response part"`
// description: |
// XPath allows using xpath expressions to extract items from html response
//
// examples:
// - value: >
// []string{"/html/body/div/p[2]/a"}
XPath []string `yaml:"xpath,omitempty" jsonschema:"title=html xpath expressions to extract data,description=XPath allows using xpath expressions to extract items from html response"`
XPath []string `yaml:"xpath,omitempty" json:"xpath,omitempty" jsonschema:"title=html xpath expressions to extract data,description=XPath allows using xpath expressions to extract items from html response"`
// description: |
// Attribute is an optional attribute to extract from response XPath.
//
// examples:
// - value: "\"href\""
Attribute string `yaml:"attribute,omitempty" jsonschema:"title=optional attribute to extract from xpath,description=Optional attribute to extract from response XPath"`
Attribute string `yaml:"attribute,omitempty" json:"attribute,omitempty" jsonschema:"title=optional attribute to extract from xpath,description=Optional attribute to extract from response XPath"`

// jsonCompiled is the compiled variant
jsonCompiled []*gojq.Code

// description: |
// Extracts using DSL expressions.
DSL []string `yaml:"dsl,omitempty" jsonschema:"title=dsl expressions to extract,description=Optional attribute to extract from response dsl"`
DSL []string `yaml:"dsl,omitempty" json:"dsl,omitempty" jsonschema:"title=dsl expressions to extract,description=Optional attribute to extract from response dsl"`
dslCompiled []*govaluate.EvaluableExpression

// description: |
Expand All @@ -101,16 +101,16 @@ type Extractor struct {
// examples:
// - value: "\"body\""
// - value: "\"raw\""
Part string `yaml:"part,omitempty" jsonschema:"title=part of response to extract data from,description=Part of the request response to extract data from"`
Part string `yaml:"part,omitempty" json:"part,omitempty" jsonschema:"title=part of response to extract data from,description=Part of the request response to extract data from"`
// description: |
// Internal, when set to true will allow using the value extracted
// in the next request for some protocols (like HTTP).
Internal bool `yaml:"internal,omitempty" jsonschema:"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"`
Internal bool `yaml:"internal,omitempty" json:"internal,omitempty" jsonschema:"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"`

// description: |
// CaseInsensitive enables case-insensitive extractions. Default is false.
// values:
// - false
// - true
CaseInsensitive bool `yaml:"case-insensitive,omitempty" jsonschema:"title=use case insensitive extract,description=use case insensitive extract"`
CaseInsensitive bool `yaml:"case-insensitive,omitempty" json:"case-insensitive,omitempty" jsonschema:"title=use case insensitive extract,description=use case insensitive extract"`
}
28 changes: 14 additions & 14 deletions v2/pkg/operators/matchers/matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import (
type Matcher struct {
// description: |
// Type is the type of the matcher.
Type MatcherTypeHolder `yaml:"type" jsonschema:"title=type of matcher,description=Type of the matcher,enum=status,enum=size,enum=word,enum=regex,enum=binary,enum=dsl"`
Type MatcherTypeHolder `yaml:"type" json:"type" jsonschema:"title=type of matcher,description=Type of the matcher,enum=status,enum=size,enum=word,enum=regex,enum=binary,enum=dsl"`
// description: |
// Condition is the optional condition between two matcher variables. By default,
// the condition is assumed to be OR.
// values:
// - "and"
// - "or"
Condition string `yaml:"condition,omitempty" jsonschema:"title=condition between matcher variables,description=Condition between the matcher variables,enum=and,enum=or"`
Condition string `yaml:"condition,omitempty" json:"condition,omitempty" jsonschema:"title=condition between matcher variables,description=Condition between the matcher variables,enum=and,enum=or"`

// description: |
// Part is the part of the request response to match data from.
Expand All @@ -27,31 +27,31 @@ type Matcher struct {
// examples:
// - value: "\"body\""
// - value: "\"raw\""
Part string `yaml:"part,omitempty" jsonschema:"title=part of response to match,description=Part of response to match data from"`
Part string `yaml:"part,omitempty" json:"part,omitempty" jsonschema:"title=part of response to match,description=Part of response to match data from"`

// description: |
// Negative specifies if the match should be reversed
// It will only match if the condition is not true.
Negative bool `yaml:"negative,omitempty" jsonschema:"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"`
Negative bool `yaml:"negative,omitempty" json:"negative,omitempty" jsonschema:"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"`

// description: |
// Name of the matcher. Name should be lowercase and must not contain
// spaces or underscores (_).
// examples:
// - value: "\"cookie-matcher\""
Name string `yaml:"name,omitempty" jsonschema:"title=name of the matcher,description=Name of the matcher"`
Name string `yaml:"name,omitempty" json:"name,omitempty" jsonschema:"title=name of the matcher,description=Name of the matcher"`
// description: |
// Status are the acceptable status codes for the response.
// examples:
// - value: >
// []int{200, 302}
Status []int `yaml:"status,omitempty" jsonschema:"title=status to match,description=Status to match for the response"`
Status []int `yaml:"status,omitempty" json:"status,omitempty" jsonschema:"title=status to match,description=Status to match for the response"`
// description: |
// Size is the acceptable size for the response
// examples:
// - value: >
// []int{3029, 2042}
Size []int `yaml:"size,omitempty" jsonschema:"title=acceptable size for response,description=Size is the acceptable size for the response"`
Size []int `yaml:"size,omitempty" json:"size,omitempty" jsonschema:"title=acceptable size for response,description=Size is the acceptable size for the response"`
// description: |
// Words contains word patterns required to be present in the response part.
// examples:
Expand All @@ -61,7 +61,7 @@ type Matcher struct {
// - name: Match for application/json in response headers
// value: >
// []string{"application/json"}
Words []string `yaml:"words,omitempty" jsonschema:"title=words to match in response,description= Words contains word patterns required to be present in the response part"`
Words []string `yaml:"words,omitempty" json:"words,omitempty" jsonschema:"title=words to match in response,description= Words contains word patterns required to be present in the response part"`
// description: |
// Regex contains Regular Expression patterns required to be present in the response part.
// examples:
Expand All @@ -71,7 +71,7 @@ type Matcher struct {
// - name: Match for Open Redirect via Location header
// value: >
// []string{`(?m)^(?:Location\\s*?:\\s*?)(?:https?://|//)?(?:[a-zA-Z0-9\\-_\\.@]*)example\\.com.*$`}
Regex []string `yaml:"regex,omitempty" jsonschema:"title=regex to match in response,description=Regex contains regex patterns required to be present in the response part"`
Regex []string `yaml:"regex,omitempty" json:"regex,omitempty" jsonschema:"title=regex to match in response,description=Regex contains regex patterns required to be present in the response part"`
// description: |
// Binary are the binary patterns required to be present in the response part.
// examples:
Expand All @@ -81,7 +81,7 @@ type Matcher struct {
// - name: Match for 7zip files
// value: >
// []string{"377ABCAF271C"}
Binary []string `yaml:"binary,omitempty" jsonschema:"title=binary patterns to match in response,description=Binary are the binary patterns required to be present in the response part"`
Binary []string `yaml:"binary,omitempty" json:"binary,omitempty" jsonschema:"title=binary patterns to match in response,description=Binary are the binary patterns required to be present in the response part"`
// description: |
// 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/).
Expand All @@ -92,24 +92,24 @@ type Matcher struct {
// - name: DSL Matcher for missing strict transport security header
// value: >
// []string{"!contains(tolower(all_headers), ''strict-transport-security'')"}
DSL []string `yaml:"dsl,omitempty" jsonschema:"title=dsl expressions to match in response,description=DSL are the dsl expressions that will be evaluated as part of nuclei matching rules"`
DSL []string `yaml:"dsl,omitempty" json:"dsl,omitempty" jsonschema:"title=dsl expressions to match in response,description=DSL are the dsl expressions that will be evaluated as part of nuclei matching rules"`
// description: |
// Encoding specifies the encoding for the words field if any.
// values:
// - "hex"
Encoding string `yaml:"encoding,omitempty" jsonschema:"title=encoding for word field,description=Optional encoding for the word fields,enum=hex"`
Encoding string `yaml:"encoding,omitempty" json:"encoding,omitempty" jsonschema:"title=encoding for word field,description=Optional encoding for the word fields,enum=hex"`
// description: |
// CaseInsensitive enables case-insensitive matches. Default is false.
// values:
// - false
// - true
CaseInsensitive bool `yaml:"case-insensitive,omitempty" jsonschema:"title=use case insensitive match,description=use case insensitive match"`
CaseInsensitive bool `yaml:"case-insensitive,omitempty" json:"case-insensitive,omitempty" jsonschema:"title=use case insensitive match,description=use case insensitive match"`
// description: |
// MatchAll enables matching for all matcher values. Default is false.
// values:
// - false
// - true
MatchAll bool `yaml:"match-all,omitempty" jsonschema:"title=match all values,description=match all matcher values ignoring condition"`
MatchAll bool `yaml:"match-all,omitempty" json:"match-all,omitempty" jsonschema:"title=match all values,description=match all matcher values ignoring condition"`

// cached data for the compiled matcher
condition ConditionType
Expand Down
14 changes: 14 additions & 0 deletions v2/pkg/operators/matchers/matchers_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ func (holder *MatcherTypeHolder) UnmarshalYAML(unmarshal func(interface{}) error
return nil
}

func (holder *MatcherTypeHolder) UnmarshalJSON(data []byte) error {
s := strings.Trim(string(data), `"`)
if s == "" {
return nil
}
computedType, err := toMatcherTypes(s)
if err != nil {
return err
}

holder.MatcherType = computedType
return nil
}

func (holder MatcherTypeHolder) MarshalJSON() ([]byte, error) {
return json.Marshal(holder.MatcherType.String())
}
Expand Down
6 changes: 3 additions & 3 deletions v2/pkg/operators/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ type Operators struct {
//
// Multiple matchers can be combined with `matcher-condition` flag
// which accepts either `and` or `or` as argument.
Matchers []*matchers.Matcher `yaml:"matchers,omitempty" jsonschema:"title=matchers to run on response,description=Detection mechanism to identify whether the request was successful by doing pattern matching"`
Matchers []*matchers.Matcher `yaml:"matchers,omitempty" json:"matchers,omitempty" jsonschema:"title=matchers to run on response,description=Detection mechanism to identify whether the request was successful by doing pattern matching"`
// description: |
// Extractors contains the extraction mechanism for the request to identify
// and extract parts of the response.
Extractors []*extractors.Extractor `yaml:"extractors,omitempty" jsonschema:"title=extractors to run on response,description=Extractors contains the extraction mechanism for the request to identify and extract parts of the response"`
Extractors []*extractors.Extractor `yaml:"extractors,omitempty" json:"extractors,omitempty" jsonschema:"title=extractors to run on response,description=Extractors contains the extraction mechanism for the request to identify and extract parts of the response"`
// description: |
// MatchersCondition is the condition between the matchers. Default is OR.
// values:
// - "and"
// - "or"
MatchersCondition string `yaml:"matchers-condition,omitempty" jsonschema:"title=condition between the matchers,description=Conditions between the matchers,enum=and,enum=or"`
MatchersCondition string `yaml:"matchers-condition,omitempty" json:"matchers-condition,omitempty" jsonschema:"title=condition between the matchers,description=Conditions between the matchers,enum=and,enum=or"`
// cached variables that may be used along with request.
matchersCondition matchers.ConditionType

Expand Down
14 changes: 14 additions & 0 deletions v2/pkg/protocols/common/generators/attack_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ func (holder *AttackTypeHolder) UnmarshalYAML(unmarshal func(interface{}) error)
return nil
}

func (holder *AttackTypeHolder) UnmarshalJSON(data []byte) error {
s := strings.Trim(string(data), `"`)
if s == "" {
return nil
}
computedType, err := toAttackType(s)
if err != nil {
return err
}

holder.Value = computedType
return nil
}

func (holder *AttackTypeHolder) MarshalJSON() ([]byte, error) {
return json.Marshal(holder.Value.String())
}
Expand Down
14 changes: 14 additions & 0 deletions v2/pkg/protocols/common/variables/variables.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package variables

import (
"encoding/json"
"strings"

"github.com/alecthomas/jsonschema"
Expand Down Expand Up @@ -39,6 +40,19 @@ func (variables *Variable) UnmarshalYAML(unmarshal func(interface{}) error) erro
return nil
}

func (variables *Variable) UnmarshalJSON(data []byte) error {
variables.InsertionOrderedStringMap = utils.InsertionOrderedStringMap{}
if err := json.Unmarshal(data, &variables.InsertionOrderedStringMap); err != nil {
return err
}
evaluated := variables.Evaluate(map[string]interface{}{})

for k, v := range evaluated {
variables.Set(k, v)
}
return nil
}

// Evaluate returns a finished map of variables based on set values
func (variables *Variable) Evaluate(values map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{}, variables.Len())
Expand Down
Loading