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 logic bug in request[s] matcher condition #4064

Merged
merged 2 commits into from
Aug 18, 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/http/interactsh-requests-mc-and.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
id: interactsh-requests-mc-and

info:
name: interactsh multi request matcher condition
author: pdteam
severity: info

requests:
- raw:
- |
GET /api/geoping/{{interactsh-url}} HTTP/1.1
Host: {{Hostname}}

- |
GET / HTTP/1.1
Host: {{Hostname}}

matchers-condition: and
matchers:
- type: word
part: interactsh_protocol # Confirms the DNS Interaction
words:
- "dns"

- type: dsl
dsl:
- "status_code_2 == 200"
10 changes: 10 additions & 0 deletions v2/cmd/integration-test/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -1465,3 +1465,13 @@ func (h *httpDisablePathAutomerge) Execute(filePath string) error {
}
return expectResultsCount(got, 2)
}

type httpInteractshRequestsWithMCAnd struct{}

func (h *httpInteractshRequestsWithMCAnd) Execute(filePath string) error {
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, "honey.scanme.sh", debug)
if err != nil {
return err
}
return expectResultsCount(got, 1)
}
1 change: 1 addition & 0 deletions v2/cmd/integration-test/interactsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ var interactshTestCases = []TestCaseInfo{
{Path: "http/interactsh.yaml", TestCase: &httpInteractshRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
{Path: "http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
{Path: "http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
{Path: "http/interactsh-requests-mc-and.yaml", TestCase: &httpInteractshRequestsWithMCAnd{}},
}
11 changes: 9 additions & 2 deletions v2/pkg/protocols/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
"github.com/projectdiscovery/rawhttp"
sliceutil "github.com/projectdiscovery/utils/slice"
stringsutil "github.com/projectdiscovery/utils/strings"
urlutil "github.com/projectdiscovery/utils/url"
)
Expand Down Expand Up @@ -342,6 +343,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa

var gotDynamicValues map[string][]string
var requestErr error

for {
// returns two values, error and skip, which skips the execution for the request instance.
executeFunc := func(data string, payloads, dynamicValue map[string]interface{}) (bool, error) {
Expand Down Expand Up @@ -375,15 +377,20 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
}
var gotMatches bool
err = request.executeRequest(input, generatedHttpRequest, previous, hasInteractMatchers, func(event *output.InternalWrappedEvent) {
if hasInteractMarkers && hasInteractMatchers && request.options.Interactsh != nil {
// a special case where operators has interactsh matchers and multiple request are made
// ex: status_code_2 , interactsh_protocol (from 1st request) etc
needsRequestEvent := interactsh.HasMatchers(request.CompiledOperators) && request.NeedsRequestCondition()
if (hasInteractMarkers || needsRequestEvent) && request.options.Interactsh != nil {
requestData := &interactsh.RequestData{
MakeResultFunc: request.MakeResultEvent,
Event: event,
Operators: request.CompiledOperators,
MatchFunc: request.Match,
ExtractFunc: request.Extract,
}
request.options.Interactsh.RequestEvent(generatedHttpRequest.interactshURLs, requestData)
allOASTUrls := getInteractshURLsFromEvent(event.InternalEvent)
allOASTUrls = append(allOASTUrls, generatedHttpRequest.interactshURLs...)
request.options.Interactsh.RequestEvent(sliceutil.Dedupe(allOASTUrls), requestData)
gotMatches = request.options.Interactsh.AlreadyMatched(requestData)
}
// Add the extracts to the dynamic values if any.
Expand Down
15 changes: 15 additions & 0 deletions v2/pkg/protocols/http/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (
"golang.org/x/text/transform"

"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
"github.com/projectdiscovery/rawhttp"
mapsutil "github.com/projectdiscovery/utils/maps"
stringsutil "github.com/projectdiscovery/utils/strings"
)

Expand Down Expand Up @@ -163,3 +165,16 @@ func isContentTypeGbk(contentType string) bool {
contentType = strings.ToLower(contentType)
return stringsutil.ContainsAny(contentType, "gbk", "gb2312", "gb18030")
}

// if template contains more than 1 request and matchers require requestcondition from
// both requests , then we need to request for event from interactsh even if current request
// doesnot use interactsh url in it
func getInteractshURLsFromEvent(event map[string]interface{}) []string {
interactshUrls := map[string]struct{}{}
for k, v := range event {
if strings.HasPrefix(k, "interactsh-url") {
interactshUrls[types.ToString(v)] = struct{}{}
}
}
return mapsutil.GetKeys(interactshUrls)
}
Loading