Skip to content

Commit

Permalink
js: generate matcher-status event
Browse files Browse the repository at this point in the history
  • Loading branch information
tarunKoyalwar committed Jul 26, 2024
1 parent 33dbb51 commit 3807836
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 65 deletions.
18 changes: 17 additions & 1 deletion pkg/js/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ type ExecuteArgs struct {
TemplateCtx map[string]interface{} // templateCtx contains template scoped variables
}

func (e *ExecuteArgs) Map() map[string]interface{} {
return generators.MergeMaps(e.TemplateCtx, e.Args)
}

// NewExecuteArgs returns a new execute arguments.
func NewExecuteArgs() *ExecuteArgs {
return &ExecuteArgs{
Expand All @@ -66,12 +70,22 @@ func NewExecuteArgs() *ExecuteArgs {
// ExecuteResult is the result of executing a script.
type ExecuteResult map[string]interface{}

func (e ExecuteResult) Map() map[string]interface{} {
if e == nil {
return make(map[string]interface{})
}
return e
}

func NewExecuteResult() ExecuteResult {
return make(map[string]interface{})
}

// GetSuccess returns whether the script was successful or not.
func (e ExecuteResult) GetSuccess() bool {
if e == nil {
return false
}
val, ok := e["success"].(bool)
if !ok {
return false
Expand Down Expand Up @@ -114,7 +128,9 @@ func (c *Compiler) ExecuteWithOptions(program *goja.Program, args *ExecuteArgs,
if val, ok := err.(*goja.Exception); ok {
err = val.Unwrap()
}
return nil, err
e := NewExecuteResult()
e["error"] = err.Error()
return e, err
}
var res ExecuteResult
if opts.exports != nil {
Expand Down
150 changes: 86 additions & 64 deletions pkg/protocols/javascript/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
iputil "github.com/projectdiscovery/utils/ip"
mapsutil "github.com/projectdiscovery/utils/maps"
syncutil "github.com/projectdiscovery/utils/sync"
urlutil "github.com/projectdiscovery/utils/url"
)
Expand Down Expand Up @@ -346,17 +347,33 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
TimeoutVariants: requestOptions.Options.GetTimeouts(),
Source: &request.PreCondition, Context: target.Context(),
})
if err != nil {
return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err)
}
if !result.GetSuccess() || types.ToString(result["error"]) != "" {
gologger.Warning().Msgf("[%s] Precondition for request %s was not satisfied\n", request.TemplateID, request.PreCondition)
request.options.Progress.IncrementFailedRequestsBy(1)
return nil
}
if request.options.Options.Debug || request.options.Options.DebugRequests {
request.options.Progress.IncrementRequests()
gologger.Debug().Msgf("[%s] Precondition for request was satisfied\n", request.TemplateID)
// if precondition was successful
if err == nil && result.GetSuccess() {
if request.options.Options.Debug || request.options.Options.DebugRequests {
request.options.Progress.IncrementRequests()
gologger.Debug().Msgf("[%s] Precondition for request was satisfied\n", request.TemplateID)
}
} else {
var outError error
// if js code failed to execute
if err != nil {
outError = errkit.Append(errkit.New("pre-condition not satisfied skipping template execution"), err)
} else {
// execution successful but pre-condition returned false
outError = errkit.New("pre-condition not satisfied skipping template execution")
}
results := map[string]interface{}(result)
results["error"] = outError.Error()
// generate and return failed event
data := request.generateEventData(input, results, hostPort)
data = generators.MergeMaps(data, payloadValues)
event := eventcreator.CreateEventWithAdditionalOptions(request, data, request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
allVars := argsCopy.Map()
allVars = generators.MergeMaps(allVars, data)
wrappedEvent.OperatorsResult.PayloadValues = allVars
})
callback(event)
return err
}
}

Expand Down Expand Up @@ -531,24 +548,72 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
}
}

values := mapsutil.Merge(payloadValues, results)
// generate event data
data := request.generateEventData(input, values, hostPort)

// add and get values from templatectx
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.GetID(), data)
data = generators.MergeMaps(data, request.options.GetTemplateCtx(input.MetaInput).GetAll())

if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse {
msg := fmt.Sprintf("[%s] Dumped Javascript response for %s:\n%v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(results))
if requestOptions.Options.Debug || requestOptions.Options.DebugRequests {
gologger.Debug().Str("address", input.MetaInput.Input).Msg(msg)
}
if requestOptions.Options.StoreResponse {
request.options.Output.WriteStoreDebugData(input.MetaInput.Input, request.options.TemplateID, request.Type().String(), msg)
}
}

if _, ok := data["error"]; ok {
event := eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
wrappedEvent.OperatorsResult.PayloadValues = payload
})
callback(event)
return err
}

if request.options.Interactsh != nil {
request.options.Interactsh.MakePlaceholders(interactshURLs, data)
}

var event *output.InternalWrappedEvent
if len(interactshURLs) == 0 {
event = eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
wrappedEvent.OperatorsResult.PayloadValues = payload
})
callback(event)
} else if request.options.Interactsh != nil {
event = &output.InternalWrappedEvent{InternalEvent: data, UsesInteractsh: true}
request.options.Interactsh.RequestEvent(interactshURLs, &interactsh.RequestData{
MakeResultFunc: request.MakeResultEvent,
Event: event,
Operators: request.CompiledOperators,
MatchFunc: request.Match,
ExtractFunc: request.Extract,
})
}
return nil
}

// generateEventData generates event data for the request
func (request *Request) generateEventData(input *contextargs.Context, values map[string]interface{}, matched string) map[string]interface{} {
data := make(map[string]interface{})
for k, v := range payloadValues {
for k, v := range values {
data[k] = v
}
data["type"] = request.Type().String()
for k, v := range results {
data[k] = v
}
data["request-pre-condition"] = beautifyJavascript(request.PreCondition)
data["request"] = beautifyJavascript(request.Code)
data["host"] = input.MetaInput.Input
data["matched"] = hostPort
data["template-path"] = requestOptions.TemplatePath
data["template-id"] = requestOptions.TemplateID
data["template-info"] = requestOptions.TemplateInfo
data["matched"] = matched
data["template-path"] = request.options.TemplatePath
data["template-id"] = request.options.TemplateID
data["template-info"] = request.options.TemplateInfo
if request.StopAtFirstMatch || request.options.StopAtFirstMatch {
data["stop-at-first-match"] = true
}

// add ip address to data
if input.MetaInput.CustomIP != "" {
data["ip"] = input.MetaInput.CustomIP
Expand Down Expand Up @@ -588,50 +653,7 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
}
}
}

// add and get values from templatectx
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.GetID(), data)
data = generators.MergeMaps(data, request.options.GetTemplateCtx(input.MetaInput).GetAll())

if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse {
msg := fmt.Sprintf("[%s] Dumped Javascript response for %s:\n%v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(results))
if requestOptions.Options.Debug || requestOptions.Options.DebugRequests {
gologger.Debug().Str("address", input.MetaInput.Input).Msg(msg)
}
if requestOptions.Options.StoreResponse {
request.options.Output.WriteStoreDebugData(input.MetaInput.Input, request.options.TemplateID, request.Type().String(), msg)
}
}

if _, ok := data["error"]; ok {
event := eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
wrappedEvent.OperatorsResult.PayloadValues = payload
})
callback(event)
return err
}

if request.options.Interactsh != nil {
request.options.Interactsh.MakePlaceholders(interactshURLs, data)
}

var event *output.InternalWrappedEvent
if len(interactshURLs) == 0 {
event = eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(data, payloadValues), request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
wrappedEvent.OperatorsResult.PayloadValues = payload
})
callback(event)
} else if request.options.Interactsh != nil {
event = &output.InternalWrappedEvent{InternalEvent: data, UsesInteractsh: true}
request.options.Interactsh.RequestEvent(interactshURLs, &interactsh.RequestData{
MakeResultFunc: request.MakeResultEvent,
Event: event,
Operators: request.CompiledOperators,
MatchFunc: request.Match,
ExtractFunc: request.Extract,
})
}
return nil
return data
}

func (request *Request) getArgsCopy(input *contextargs.Context, payloadValues map[string]interface{}, requestOptions *protocols.ExecutorOptions, ignoreErrors bool) (*compiler.ExecuteArgs, error) {
Expand Down

0 comments on commit 3807836

Please sign in to comment.