introduce `self-contained` to headless (#4322)

* introduce `self-contained` to headless

* fix matched url print
dev
Dogan Can Bakir 2023-11-02 16:38:20 +03:00 committed by GitHub
parent 595ba8e3a5
commit 83abe0969e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 1 deletions

View File

@ -12,6 +12,7 @@ import (
var headlessTestcases = []TestCaseInfo{
{Path: "protocols/headless/headless-basic.yaml", TestCase: &headlessBasic{}},
{Path: "protocols/headless/headless-self-contained.yaml", TestCase: &headlessSelfContained{}},
{Path: "protocols/headless/headless-header-action.yaml", TestCase: &headlessHeaderActions{}},
{Path: "protocols/headless/headless-extract-values.yaml", TestCase: &headlessExtractValues{}},
{Path: "protocols/headless/headless-payloads.yaml", TestCase: &headlessPayloads{}},
@ -41,6 +42,18 @@ func (h *headlessBasic) Execute(filePath string) error {
return expectResultsCount(results, 1)
}
type headlessSelfContained struct{}
// Execute executes a test case and returns an error if occurred
func (h *headlessSelfContained) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-headless", "-var query=selfcontained")
if err != nil {
return err
}
return expectResultsCount(results, 1)
}
type headlessLocal struct{}
// Execute executes a test case and returns an error if occurred

View File

@ -0,0 +1,20 @@
id: headless-self-contained
info:
name: Headless Self Contained
author: pdteam
severity: info
tags: headless
self-contained: true
headless:
- steps:
- action: navigate
args:
url: "https://postman-echo.com/get?q={{query}}"
- action: waitload
matchers:
- type: word
words:
- "selfcontained"

View File

@ -59,6 +59,10 @@ type Request struct {
// Fuzzing describes schema to fuzz headless requests
Fuzzing []*fuzz.Rule `yaml:"fuzzing,omitempty" json:"fuzzing,omitempty" jsonschema:"title=fuzzin rules for http fuzzing,description=Fuzzing describes rule schema to fuzz headless requests"`
// description: |
// SelfContained specifies if the request is self-contained.
SelfContained bool `yaml:"-" json:"-"`
// description: |
// CookieReuse is an optional setting that enables cookie reuse
CookieReuse bool `yaml:"cookie-reuse,omitempty" json:"cookie-reuse,omitempty" jsonschema:"title=optional cookie reuse enable,description=Optional setting that enables cookie reuse"`

View File

@ -39,6 +39,14 @@ func (request *Request) Type() templateTypes.ProtocolType {
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
if request.SelfContained {
url, err := extractBaseURLFromActions(request.Steps)
if err != nil {
return err
}
input = contextargs.NewWithInput(url)
}
if request.options.Browser.UserAgent() == "" {
request.options.Browser.SetUserAgent(request.compiledUserAgent)
}
@ -86,6 +94,21 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata,
return nil
}
// This function extracts the base URL from actions.
func extractBaseURLFromActions(steps []*engine.Action) (string, error) {
for _, action := range steps {
if action.ActionType.ActionType == engine.ActionNavigate {
navigateURL := action.GetArg("url")
url, err := urlutil.Parse(navigateURL)
if err != nil {
return "", errors.Errorf("could not parse URL '%s': %s", navigateURL, err.Error())
}
return fmt.Sprintf("%s://%s", url.Scheme, url.Host), nil
}
}
return "", errors.New("no navigation action found")
}
func (request *Request) executeRequestWithPayloads(input *contextargs.Context, payloads map[string]interface{}, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
instance, err := request.options.Browser.NewInstance()
if err != nil {
@ -157,7 +180,7 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
responseBody, _ = html.HTML()
}
outputEvent := request.responseToDSLMap(responseBody, out["header"], out["status_code"], reqBuilder.String(), input.MetaInput.Input, input.MetaInput.Input, page.DumpHistory())
outputEvent := request.responseToDSLMap(responseBody, out["header"], out["status_code"], reqBuilder.String(), input.MetaInput.Input, navigatedURL, page.DumpHistory())
// add response fields to template context and merge templatectx variables to output event
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent)
outputEvent = generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll())

View File

@ -110,6 +110,9 @@ func (template *Template) parseSelfContainedRequests() {
for _, request := range template.RequestsNetwork {
request.SelfContained = true
}
for _, request := range template.RequestsHeadless {
request.SelfContained = true
}
}
// Requests returns the total request count for the template