From c701e2ad4aede507a07be4bd7530476a0cb05fd2 Mon Sep 17 00:00:00 2001 From: mzack Date: Mon, 31 Jan 2022 08:52:36 +0100 Subject: [PATCH] adding support for interactsh --- v2/go.mod | 4 +-- v2/go.sum | 8 ++--- v2/pkg/protocols/headless/engine/instance.go | 9 +++++ v2/pkg/protocols/headless/engine/page.go | 34 ++++++++++++------- .../protocols/headless/engine/page_actions.go | 8 ++++- v2/pkg/protocols/headless/request.go | 23 +++++++++++-- 6 files changed, 64 insertions(+), 22 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index cb3da7c6..2531176b 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -33,7 +33,7 @@ require ( github.com/projectdiscovery/goflags v0.0.8-0.20220121110825-48035ad3ffe0 github.com/projectdiscovery/gologger v1.1.4 github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa - github.com/projectdiscovery/interactsh v0.0.8-0.20220112083504-b0b3b2f359a5 + github.com/projectdiscovery/interactsh v1.0.1-0.20220131074403-ca8bb8f87cd0 github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df github.com/projectdiscovery/rawhttp v0.0.7 github.com/projectdiscovery/retryabledns v1.0.13-0.20211109182249-43d38df59660 @@ -112,7 +112,7 @@ require ( github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect github.com/itchyny/timefmt-go v0.1.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.13.6 // indirect + github.com/klauspost/compress v1.14.1 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/leodido/go-urn v1.2.1 // indirect diff --git a/v2/go.sum b/v2/go.sum index c7794ca6..ca91ab0c 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -305,8 +305,8 @@ github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.1 h1:hLQYb23E8/fO+1u53d02A97a8UnsddcvYzq4ERRU4ds= +github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -428,8 +428,8 @@ github.com/projectdiscovery/hmap v0.0.2-0.20210616215655-7b78e7f33d1f/go.mod h1: github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa h1:9sZWFUAshIa/ea0RKjGRuuZiS5PzYXAFjTRUnSbezr0= github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa/go.mod h1:lV5f/PNPmCCjCN/dR317/chN9s7VG5h/xcbFfXOz8Fo= github.com/projectdiscovery/interactsh v0.0.4/go.mod h1:PtJrddeBW1/LeOVgTvvnjUl3Hu/17jTkoIi8rXeEODE= -github.com/projectdiscovery/interactsh v0.0.8-0.20220112083504-b0b3b2f359a5 h1:PXwVuZCnB9xpx075zcZh4lj0ZpJY/dfvuw+Ok5Hqyf4= -github.com/projectdiscovery/interactsh v0.0.8-0.20220112083504-b0b3b2f359a5/go.mod h1:jXtAbjMnesRxBLY70m9DLXRwVp88gWueOtXfgj49b+Q= +github.com/projectdiscovery/interactsh v1.0.1-0.20220131074403-ca8bb8f87cd0 h1:Olf2RG9sLqZF157gC664G6A3DU0Fta6VD/OWiNP3LbI= +github.com/projectdiscovery/interactsh v1.0.1-0.20220131074403-ca8bb8f87cd0/go.mod h1:UW8wdok5mrDOXzcHxRjUCCDIScc/3hCpw8QjVDeXHEE= github.com/projectdiscovery/ipranger v0.0.2/go.mod h1:kcAIk/lo5rW+IzUrFkeYyXnFJ+dKwYooEOHGVPP/RWE= github.com/projectdiscovery/iputil v0.0.0-20210414194613-4b4d2517acf0/go.mod h1:PQAqn5h5NXsQTF4ZA00ZTYLRzGCjOtcCq8llAqrsd1A= github.com/projectdiscovery/iputil v0.0.0-20210429152401-c18a5408ca46/go.mod h1:PQAqn5h5NXsQTF4ZA00ZTYLRzGCjOtcCq8llAqrsd1A= diff --git a/v2/pkg/protocols/headless/engine/instance.go b/v2/pkg/protocols/headless/engine/instance.go index 3b2db22e..90ffccac 100644 --- a/v2/pkg/protocols/headless/engine/instance.go +++ b/v2/pkg/protocols/headless/engine/instance.go @@ -7,12 +7,16 @@ import ( "github.com/go-rod/rod" "github.com/go-rod/rod/lib/utils" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh" ) // Instance is an isolated browser instance opened for doing operations with it. type Instance struct { browser *Browser engine *rod.Browser + + // redundant due to dependency cycle + interactsh *interactsh.Client } // NewInstance creates a new instance for the current browser. @@ -39,6 +43,11 @@ func (i *Instance) Close() error { return i.engine.Close() } +// SetInteractsh client +func (i *Instance) SetInteractsh(interactsh *interactsh.Client) { + i.interactsh = interactsh +} + // maxBackoffSleeper is a backoff sleeper respecting max backoff values func maxBackoffSleeper(max int) utils.Sleeper { count := 0 diff --git a/v2/pkg/protocols/headless/engine/page.go b/v2/pkg/protocols/headless/engine/page.go index 6543a8fb..400eab43 100644 --- a/v2/pkg/protocols/headless/engine/page.go +++ b/v2/pkg/protocols/headless/engine/page.go @@ -12,12 +12,13 @@ import ( // Page is a single page in an isolated browser instance type Page struct { - page *rod.Page - rules []requestRule - instance *Instance - router *rod.HijackRouter - historyMutex *sync.RWMutex - History []HistoryData + page *rod.Page + rules []requestRule + instance *Instance + router *rod.HijackRouter + mutex *sync.RWMutex + History []HistoryData + InteractshURLs []string } // HistoryData contains the page request/response pairs @@ -40,7 +41,7 @@ func (i *Instance) Run(baseURL *url.URL, actions []*Action, timeout time.Duratio } } - createdPage := &Page{page: page, instance: i, historyMutex: &sync.RWMutex{}} + createdPage := &Page{page: page, instance: i, mutex: &sync.RWMutex{}} router := page.HijackRequests() if routerErr := router.Add("*", "", createdPage.routingRuleHandler); routerErr != nil { return nil, nil, routerErr @@ -94,8 +95,8 @@ func (p *Page) URL() string { // DumpHistory returns the full page navigation history func (p *Page) DumpHistory() string { - p.historyMutex.RLock() - defer p.historyMutex.RUnlock() + p.mutex.RLock() + defer p.mutex.RUnlock() var historyDump strings.Builder for _, historyData := range p.History { @@ -106,9 +107,16 @@ func (p *Page) DumpHistory() string { } // addToHistory adds a request/response pair to the page history -func (p *Page) addToHistory(historyData HistoryData) { - p.historyMutex.Lock() - defer p.historyMutex.Unlock() +func (p *Page) addToHistory(historyData ...HistoryData) { + p.mutex.Lock() + defer p.mutex.Unlock() - p.History = append(p.History, historyData) + p.History = append(p.History, historyData...) +} + +func (p *Page) addInteractshURL(URLs ...string) { + p.mutex.Lock() + defer p.mutex.Unlock() + + p.InteractshURLs = append(p.InteractshURLs, URLs...) } diff --git a/v2/pkg/protocols/headless/engine/page_actions.go b/v2/pkg/protocols/headless/engine/page_actions.go index 2b161eff..60f954b6 100644 --- a/v2/pkg/protocols/headless/engine/page_actions.go +++ b/v2/pkg/protocols/headless/engine/page_actions.go @@ -627,5 +627,11 @@ func (p *Page) getActionArgWithDefaultValues(action *Action, arg string) string func (p *Page) getActionArgWithValues(action *Action, arg string, values map[string]interface{}) string { argValue := action.GetArg(arg) - return replaceWithValues(argValue, values) + argValue = replaceWithValues(argValue, values) + if p.instance.interactsh != nil { + var interactshURLs []string + argValue, interactshURLs = p.instance.interactsh.ReplaceMarkers(argValue, p.InteractshURLs) + p.addInteractshURL(interactshURLs...) + } + return argValue } diff --git a/v2/pkg/protocols/headless/request.go b/v2/pkg/protocols/headless/request.go index 41c26884..df06e704 100644 --- a/v2/pkg/protocols/headless/request.go +++ b/v2/pkg/protocols/headless/request.go @@ -12,6 +12,7 @@ import ( "github.com/projectdiscovery/nuclei/v2/pkg/protocols" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/eventcreator" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/responsehighlighter" + "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh" templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" ) @@ -32,6 +33,8 @@ func (request *Request) ExecuteWithResults(inputURL string, metadata, previous o } defer instance.Close() + instance.SetInteractsh(request.options.Interactsh) + parsedURL, err := url.Parse(inputURL) if err != nil { request.options.Output.Request(request.options.TemplatePath, inputURL, request.Type().String(), err) @@ -66,16 +69,32 @@ func (request *Request) ExecuteWithResults(inputURL string, metadata, previous o if err == nil { responseBody, _ = html.HTML() } + outputEvent := request.responseToDSLMap(responseBody, reqBuilder.String(), inputURL, inputURL, page.DumpHistory()) for k, v := range out { outputEvent[k] = v } - event := eventcreator.CreateEvent(request, outputEvent, request.options.Options.Debug || request.options.Options.DebugResponse) + var event *output.InternalWrappedEvent + if len(page.InteractshURLs) == 0 { + event := eventcreator.CreateEvent(request, outputEvent, request.options.Options.Debug || request.options.Options.DebugResponse) + callback(event) + } else if request.options.Interactsh != nil { + event = &output.InternalWrappedEvent{InternalEvent: outputEvent} + request.options.Interactsh.RequestEvent(page.InteractshURLs, &interactsh.RequestData{ + MakeResultFunc: request.MakeResultEvent, + Event: event, + Operators: request.CompiledOperators, + MatchFunc: request.Match, + ExtractFunc: request.Extract, + }) + } + if len(page.InteractshURLs) > 0 { + event.UsesInteractsh = true + } dumpResponse(event, request.options, responseBody, inputURL) - callback(event) return nil }