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

fix showing multiple failure matches per template on -ms set #3770

Merged
merged 37 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8b45bf1
fix showing multiple failure matchers per template
RamanaReddy0M May 31, 2023
c7b5009
Merge branch 'dev' into issue-2693-bug-in-matcher-status
RamanaReddy0M Jun 1, 2023
5430b8d
exclude AS134029 from unit test
RamanaReddy0M Jun 1, 2023
1dd2c7a
Merge branch 'dev' into issue-2693-bug-in-matcher-status
RamanaReddy0M Jun 1, 2023
84c231f
Add flag for match status per request
RamanaReddy0M Jun 5, 2023
bb1afaa
Merge branch 'dev' into issue-2693-bug-in-matcher-status
RamanaReddy0M Jun 5, 2023
27a5b28
chore(deps): bump golangci/golangci-lint-action from 3.4.0 to 3.5.0 (…
dependabot[bot] Jun 5, 2023
90cf8a5
chore(deps): bump github.com/xanzy/go-gitlab in /v2 (#3778)
dependabot[bot] Jun 5, 2023
0da821f
chore(deps): bump github.com/spf13/cast from 1.5.0 to 1.5.1 in /v2 (#…
dependabot[bot] Jun 5, 2023
1da6a13
enable no-httpx when passive scan is launched (#3789)
dogancanbakir Jun 7, 2023
74a894c
chore(deps): bump github.com/projectdiscovery/fastdialer from 0.0.26 …
dependabot[bot] Jun 8, 2023
5a54296
deprecatedProtocolNameTemplates concurrent map writes (#3785)
cn-kali-team Jun 8, 2023
a4b6236
Issue 3339 headless fuzz (#3790)
ShubhamRasal Jun 9, 2023
1ced070
Auto Generate Syntax Docs + JSONSchema [Fri Jun 9 00:23:32 UTC 2023]…
actions-user Jun 9, 2023
b5d6c39
Add headless header and status matchers (#3794)
dogancanbakir Jun 9, 2023
b37d6f4
chore(deps): bump golang from 1.20.4-alpine to 1.20.5-alpine (#3809)
dependabot[bot] Jun 12, 2023
2f9483a
chore(deps): bump github.com/go-playground/validator/v10 in /v2 (#3810)
dependabot[bot] Jun 12, 2023
bee32f0
chore(deps): bump github.com/projectdiscovery/rawhttp in /v2 (#3811)
dependabot[bot] Jun 12, 2023
48d62a9
chore(deps): bump github.com/go-git/go-git/v5 from 5.6.1 to 5.7.0 in …
dependabot[bot] Jun 12, 2023
f620c07
chore(deps): bump github.com/projectdiscovery/hmap in /v2 (#3781)
dependabot[bot] Jun 12, 2023
a293d7b
Using safe dereferencing
Mzack9999 Jun 12, 2023
fd4f881
adding comment
Mzack9999 Jun 12, 2023
2e09cf5
fixing and condition
Mzack9999 Jun 13, 2023
60fcf7e
fixing test id
Mzack9999 Jun 13, 2023
42443be
adding integration test
Mzack9999 Jun 13, 2023
9b0f7a4
update goflags dependency
RamanaReddy0M Jun 15, 2023
7798802
update goflags dependency
RamanaReddy0M Jun 15, 2023
4c6da7a
bump goflags v0.1.9 => v0.1.10
RamanaReddy0M Jun 15, 2023
ca1df65
resovle merge conflicts
RamanaReddy0M Jun 21, 2023
7fa322b
handle failure matcher flags logic at executor itself
RamanaReddy0M Jun 21, 2023
ce2dfcf
add integration test to matcher status per request
RamanaReddy0M Jun 21, 2023
05d0c1f
Adding random tls impersonate (#3844)
Mzack9999 Jun 21, 2023
ec3ee2e
Use templateman enhance api to populate CVE info (#3788)
RamanaReddy0M Jun 21, 2023
23cc7f1
resolve merge conflicts
RamanaReddy0M Jun 22, 2023
eb3ee1c
fix matcher status with network protocol
RamanaReddy0M Jun 27, 2023
83761e7
fix test
RamanaReddy0M Jun 27, 2023
65a31c1
remove -msr flag
RamanaReddy0M Jun 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 40 additions & 0 deletions integration_tests/http/matcher-status-per-request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
id: matcher-status-per-request

info:
name: Test Matcher Status Per Request
author: pdteam
severity: critical

variables:
username: test
password: admin
date: 2023-05-31

http:
- method: GET
path:
- "{{RootURL}}/login?username={{username}}&password={{password}}"
- "{{BaseURL}}/admin-pannel"

- method: GET
path:
- "{{BaseURL}}/dashboard?date={{date}}"
- "{{BaseURL}}/signup"

- method: POST
path:
- "{{BaseURL}}/filemanager/upload.php"
body: "fldr=&url=file:///etc/passwd"


stop-at-first-match: true
matchers-condition: and
matchers:
- type: word
part: body
words:
- "matcher status"

- type: status
status:
- 200
40 changes: 40 additions & 0 deletions integration_tests/http/matcher-status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
id: matchet-status

info:
name: Test Matcher Status
author: pdteam
severity: critical

variables:
username: test
password: admin
date: 2023-05-31

http:
- method: GET
path:
- "{{RootURL}}/login?username={{username}}&password={{password}}"
- "{{BaseURL}}/admin-pannel"

- method: GET
path:
- "{{BaseURL}}/dashboard?date={{date}}"
- "{{BaseURL}}/signup"

- method: POST
path:
- "{{BaseURL}}/filemanager/upload.php"
body: "fldr=&url=file:///etc/passwd"


stop-at-first-match: true
matchers-condition: and
matchers:
- type: word
part: body
words:
- "matcher status"

- type: status
status:
- 200
38 changes: 38 additions & 0 deletions v2/cmd/integration-test/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ var httpTestcases = map[string]testutils.TestCase{
"http/cl-body-with-header.yaml": &httpCLBodyWithHeader{},
"http/save-extractor-values-to-file.yaml": &httpSaveExtractorValuesToFile{},
"http/cli-with-constants.yaml": &ConstantWithCliVar{},
"http/matcher-status.yaml": &matcherStatusTest{},
"http/matcher-status-per-request.yaml": &matcherStatusPerRequestTest{},
"http/disable-path-automerge.yaml": &httpDisablePathAutomerge{},
}

Expand Down Expand Up @@ -1425,6 +1427,42 @@ func (h *ConstantWithCliVar) Execute(filePath string) error {
return expectResultsCount(got, 1)
}

type matcherStatusTest struct{}

// Execute executes a test case and returns an error if occurred
func (h *matcherStatusTest) Execute(filePath string) error {
router := httprouter.New()
router.GET("/200", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.WriteHeader(http.StatusOK)
})
ts := httptest.NewServer(router)
defer ts.Close()

results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-ms")
if err != nil {
return err
}
return expectResultsCount(results, 1)
}

type matcherStatusPerRequestTest struct{}

// Execute executes a test case and returns an error if occurred
func (h *matcherStatusPerRequestTest) Execute(filePath string) error {
router := httprouter.New()
router.GET("/200", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.WriteHeader(http.StatusOK)
})
ts := httptest.NewServer(router)
defer ts.Close()

results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-msr")
if err != nil {
return err
}
return expectResultsCount(results, 5)
}

// disable path automerge in raw request
type httpDisablePathAutomerge struct{}

Expand Down
1 change: 1 addition & 0 deletions v2/cmd/nuclei/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.BoolVarP(&options.Timestamp, "timestamp", "ts", false, "enables printing timestamp in cli output"),
flagSet.StringVarP(&options.ReportingDB, "report-db", "rdb", "", "nuclei reporting database (always use this to persist report data)"),
flagSet.BoolVarP(&options.MatcherStatus, "matcher-status", "ms", false, "display match failure status"),
flagSet.BoolVarP(&options.MatchStatusPerRequest, "matcher-status-request", "msr", false, "display match failure status per request"),
flagSet.StringVarP(&options.MarkdownExportDirectory, "markdown-export", "me", "", "directory to export results in markdown format"),
flagSet.StringVarP(&options.SarifExport, "sarif-export", "se", "", "file to export results in SARIF format"),
flagSet.StringVarP(&options.JSONExport, "json-export", "je", "", "file to export results in JSON format"),
Expand Down
53 changes: 27 additions & 26 deletions v2/pkg/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ type Writer interface {

// StandardWriter is a writer writing output to file and screen for results.
type StandardWriter struct {
json bool
jsonReqResp bool
timestamp bool
noMetadata bool
matcherStatus bool
mutex *sync.Mutex
aurora aurora.Aurora
outputFile io.WriteCloser
traceFile io.WriteCloser
errorFile io.WriteCloser
severityColors func(severity.Severity) string
storeResponse bool
storeResponseDir string
json bool
jsonReqResp bool
timestamp bool
noMetadata bool
matcherStatus bool
mutex *sync.Mutex
aurora aurora.Aurora
outputFile io.WriteCloser
traceFile io.WriteCloser
errorFile io.WriteCloser
severityColors func(severity.Severity) string
storeResponse bool
storeResponseDir string
}

var decolorizerRegex = regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`)
Expand Down Expand Up @@ -187,20 +187,21 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
gologger.Fatal().Msgf("Could not create output directory '%s': %s\n", options.StoreResponseDir, err)
}
}

writer := &StandardWriter{
json: options.JSONL,
jsonReqResp: options.JSONRequests,
noMetadata: options.NoMeta,
matcherStatus: options.MatcherStatus,
timestamp: options.Timestamp,
aurora: auroraColorizer,
mutex: &sync.Mutex{},
outputFile: outputFile,
traceFile: traceOutput,
errorFile: errorOutput,
severityColors: colorizer.New(auroraColorizer),
storeResponse: options.StoreResponse,
storeResponseDir: options.StoreResponseDir,
json: options.JSONL,
jsonReqResp: options.JSONRequests,
noMetadata: options.NoMeta,
matcherStatus: options.MatcherStatus || options.MatchStatusPerRequest,
timestamp: options.Timestamp,
aurora: auroraColorizer,
mutex: &sync.Mutex{},
outputFile: outputFile,
traceFile: traceOutput,
errorFile: errorOutput,
severityColors: colorizer.New(auroraColorizer),
storeResponse: options.StoreResponse,
storeResponseDir: options.StoreResponseDir,
}
return writer, nil
}
Expand Down
31 changes: 24 additions & 7 deletions v2/pkg/protocols/common/executer/executer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ func (e *Executer) Execute(input *contextargs.Context) (bool, error) {
})
}
previous := make(map[string]interface{})

var lastMatcherEvent *output.InternalWrappedEvent
writeFailureCallback := func(event *output.InternalWrappedEvent, matcherStatusPerReq, matcherStatus bool) {
if matcherStatusPerReq || matcherStatus {
results.CompareAndSwap(false, true)
}
if matcherStatus {
lastMatcherEvent = event
return
}
if matcherStatusPerReq {
if err := e.options.Output.WriteFailure(event.InternalEvent); err != nil {
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
}
}
}

for _, req := range e.requests {
inputItem := input.Clone()
if e.options.InputHelper != nil && input.MetaInput.Input != "" {
Expand All @@ -93,17 +110,13 @@ func (e *Executer) Execute(input *contextargs.Context) (bool, error) {
// If no results were found, and also interactsh is not being used
// in that case we can skip it, otherwise we've to show failure in
// case of matcher-status flag.
if !event.HasOperatorResult() && !event.UsesInteractsh {
if err := e.options.Output.WriteFailure(event.InternalEvent); err != nil {
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
}
if !event.HasOperatorResult() && !event.UsesInteractsh && e.options.Options.MatchStatusPerRequest {
RamanaReddy0M marked this conversation as resolved.
Show resolved Hide resolved
writeFailureCallback(event, e.options.Options.MatchStatusPerRequest, e.options.Options.MatcherStatus)
} else {
if writer.WriteResult(event, e.options.Output, e.options.Progress, e.options.IssuesClient) {
results.CompareAndSwap(false, true)
} else {
if err := e.options.Output.WriteFailure(event.InternalEvent); err != nil {
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
}
writeFailureCallback(event, e.options.Options.MatchStatusPerRequest, e.options.Options.MatcherStatus)
}
}
})
Expand All @@ -118,6 +131,10 @@ func (e *Executer) Execute(input *contextargs.Context) (bool, error) {
break
}
}

if lastMatcherEvent != nil {
writeFailureCallback(lastMatcherEvent, true, false)
}
return results.Load(), nil
}

Expand Down
2 changes: 2 additions & 0 deletions v2/pkg/protocols/network/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata,
actualAddress := replacer.Replace(kv.address, variables)

if err := request.executeAddress(variables, actualAddress, address, input.MetaInput.Input, kv.tls, previous, callback); err != nil {
outputEvent := request.responseToDSLMap("", "", "", address, "")
callback(&output.InternalWrappedEvent{InternalEvent: outputEvent})
gologger.Warning().Msgf("[%v] Could not make network request for (%s) : %s\n", request.options.TemplateID, actualAddress, err)
continue
}
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/protocols/network/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func TestNetworkExecuteWithResults(t *testing.T) {
})
require.Nil(t, err, "could not execute network request")
})
require.Nil(t, finalEvent, "could not get event output from request")
require.Nil(t, finalEvent.Results, "could not get event output from request")

request.Inputs[0].Type = NetworkInputTypeHolder{NetworkInputType: hexType}
request.Inputs[0].Data = hex.EncodeToString([]byte(fmt.Sprintf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", parsed.Host)))
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/testutils/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func RunNucleiBareArgsAndGetResults(debug bool, extra ...string) ([]string, erro
if debug {
fmt.Println(string(data))
}
if err != nil {
if len(data) < 1 && err != nil {
return nil, fmt.Errorf("%v: %v", err.Error(), string(data))
}
var parts []string
Expand Down
2 changes: 2 additions & 0 deletions v2/pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ type Options struct {
EnvironmentVariables bool
// MatcherStatus displays optional status for the failed matches as well
MatcherStatus bool
// MatchStatusPerRequest displays optional status for the failed matches per request
MatchStatusPerRequest bool
// ClientCertFile client certificate file (PEM-encoded) used for authenticating against scanned hosts
ClientCertFile string
// ClientKeyFile client key file (PEM-encoded) used for authenticating against scanned hosts
Expand Down