diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index b11e48ccca..1eb20cd5d6 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -86,6 +86,7 @@ var httpTestcases = []TestCaseInfo{ {Path: "protocols/http/disable-path-automerge.yaml", TestCase: &httpDisablePathAutomerge{}}, {Path: "protocols/http/http-preprocessor.yaml", TestCase: &httpPreprocessor{}}, {Path: "protocols/http/multi-request.yaml", TestCase: &httpMultiRequest{}}, + {Path: "protocols/http/multi-request-host-variable-scope.yaml", TestCase: &httpMultiRequestHostVariableScope{}}, {Path: "protocols/http/http-matcher-extractor-dy-extractor.yaml", TestCase: &httpMatcherExtractorDynamicExtractor{}}, {Path: "protocols/http/multi-http-var-sharing.yaml", TestCase: &httpMultiVarSharing{}}, {Path: "protocols/http/raw-path-single-slash.yaml", TestCase: &httpRawPathSingleSlash{}}, @@ -1707,6 +1708,18 @@ func (h *httpMultiRequest) Execute(filePath string) error { return expectResultsCount(results, 1) } +type httpMultiRequestHostVariableScope struct{} + +// Execute executes a test case and returns an error if occurred +func (h *httpMultiRequestHostVariableScope) Execute(filePath string) error { + results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "http://scanme.sh/?foo=bar", debug) + if err != nil { + return err + } + + return expectResultsCount(results, 1) +} + type httpRawPathSingleSlash struct{} func (h *httpRawPathSingleSlash) Execute(filepath string) error { diff --git a/integration_tests/protocols/http/multi-request-host-variable-scope.yaml b/integration_tests/protocols/http/multi-request-host-variable-scope.yaml new file mode 100644 index 0000000000..4531de6f32 --- /dev/null +++ b/integration_tests/protocols/http/multi-request-host-variable-scope.yaml @@ -0,0 +1,20 @@ +id: http-multi-request-host-variable-scope + +info: + name: HTTP multi request host variable scope + author: pdteam + severity: info + description: Ensures request-scoped host variables are derived from each request URL. + +http: + - method: GET + path: + - "{{BaseURL}}" + + - method: GET + path: + - "http://honey.scanme.sh" + matchers: + - type: dsl + dsl: + - http_2_host == "http://honey.scanme.sh" \ No newline at end of file diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index c8f4d447fe..295b22147c 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -250,9 +250,13 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context, return nil, errkit.Newf("failed to parse url %v while creating http request", reqData) } // while merging parameters first preference is given to target params - finalparams := parsed.Params - finalparams.Merge(reqURL.Params.Encode()) - reqURL.Params = finalparams + // only merge target params when the evaluated request host matches input host + // absolute cross-domain URLs should not inherit query params from the original input + if reqURL.Host == parsed.Host { + finalparams := parsed.Params + finalparams.Merge(reqURL.Params.Encode()) + reqURL.Params = finalparams + } return r.generateHttpRequest(ctx, reqURL, finalVars, payloads) } diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 7fb3218e7d..8b5d77edc0 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -900,7 +900,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ // In case of interactsh markers and request times out, still send // a callback event so in case we receive an interaction, correlation is possible. // Also, to log failed use-cases. - outputEvent := request.responseToDSLMap(&http.Response{}, input.MetaInput.Input, formedURL, convUtil.String(dumpedRequest), "", "", "", 0, generatedRequest.meta) + outputEvent := request.responseToDSLMap(&http.Response{}, formedURL, formedURL, convUtil.String(dumpedRequest), "", "", "", 0, generatedRequest.meta) if i := strings.LastIndex(hostname, ":"); i != -1 { hostname = hostname[:i] } @@ -1024,7 +1024,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ } } - outputEvent := request.responseToDSLMap(respChain.Response(), input.MetaInput.Input, matchedURL, convUtil.String(dumpedRequest), fullResponseStr, bodyStr, headersStr, duration, generatedRequest.meta) + outputEvent := request.responseToDSLMap(respChain.Response(), matchedURL, matchedURL, convUtil.String(dumpedRequest), fullResponseStr, bodyStr, headersStr, duration, generatedRequest.meta) // add response fields to template context and merge templatectx variables to output event request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent) if request.options.HasTemplateCtx(input.MetaInput) {