-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Is there an existing issue for this?
- I have searched the existing issues.
Current Behavior
When using nuclei with matcher-status set with clustered templates, any with a matchers-condition set to and will not trigger the mock response to return a failed result. Instead, it silently fails. This looks to have been introduced around PR #4247. I am not saying that to throw shade! That was a very large PR and it has been missed since.
The underlying issues seems to be a single template returns a nil value if the match fails. However, clustered requests where a template has a matcher-condition set to and returns a non-nil result from the operator.operator.Execute. This means it will never trigger the result == nil && !matched && e.options.Options.MatcherStatus call of the clusterExecuter.Execute function (shown below)
[...omitted for brevity...]
func (e *ClusterExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
[...omitted for brevity...]
for _, operator := range e.operators {
clonedEvent := event.CloneShallow()
result, matched := operator.operator.Execute(clonedEvent.InternalEvent, e.requests.Match, e.requests.Extract, e.options.Options.Debug || e.options.Options.DebugResponse)
clonedEvent.InternalEvent["template-id"] = operator.templateID
clonedEvent.InternalEvent["template-path"] = operator.templatePath
clonedEvent.InternalEvent["template-info"] = operator.templateInfo
if result == nil && !matched && e.options.Options.MatcherStatus {
if err := e.options.Output.WriteFailure(clonedEvent); err != nil {
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
}
continue
}
if matched && result != nil {
clonedEvent.OperatorsResult = result
clonedEvent.Results = e.requests.MakeResultEvent(clonedEvent)
results = true
_ = writer.WriteResult(clonedEvent, e.options.Output, e.options.Progress, e.options.IssuesClient)
}
}
[...omitted for brevity...]
This issue only presents itself when the requests are clustered; a fix PR to follow.
Expected Behavior
The expected behavior is that any failed result should generate a mock result when matcher-status is set to true.
Steps To Reproduce
- Create 2 identical templates that will fail to trigger a result.
- Set one of the templates to have
matchers-condition: andon the requests
matchers-condition: and
matchers:
- type: status
status:
- 500
- Run them isolated and see two positive failed results.
# Template1 (matchers-condition: or)
$ nuclei -duc -t ./template1.yaml -verbose --matcher-status -target https://oast.pro:443
[...omitted for brevity...]
[VER] [template-1] Sent HTTP request to https://oast.pro:443/
[template-1] [failed] [http] [info] oast.pro
[INF] Scan completed in 1.311599792s. 1 matches found.
# Template2 (matchers-condition: and)
$ nuclei -duc -t ./template2.yaml -verbose --matcher-status -target https://oast.pro:443
[...omitted for brevity...]
[VER] [template-2] Sent HTTP request to https://oast.pro:443/
[template-2] [failed] [http] [info] oast.pro
[INF] Scan completed in 1.158872s. 1 matches found.
- Run them together and see single failed result
$ nuclei -duc -t ./template1.yaml,./template2.yaml -verbose --matcher-status -target https://oast.pro:443
[...omitted for brevity...]
[VER] [cluster-35cfd583aa0e09c06a797dc24640c1b234eabb0389ac46799563082dd5a521fe] Sent HTTP request to https://oast.pro:443/
[template-1] [failed] [http] [info] oast.pro
[INF] Scan completed in 1.459254958s. No results found.
Relevant log output
Environment
- OS: Mac
- Nuclei: v3.7.0
- Go: 1.25.5Anything else?
No response