From b99f028a660349df4fb453507808dc8ac32408f2 Mon Sep 17 00:00:00 2001 From: Ice3man543 Date: Sun, 6 Jun 2021 15:52:13 +0530 Subject: [PATCH] Enrich file output sarif with correct file metadata --- v2/pkg/output/output.go | 2 ++ v2/pkg/protocols/file/operators.go | 30 ++++++++++++++++++++++ v2/pkg/reporting/exporters/sarif/sarif.go | 31 ++++++++++++++++++++--- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/v2/pkg/output/output.go b/v2/pkg/output/output.go index bd72c894..ffe1b180 100644 --- a/v2/pkg/output/output.go +++ b/v2/pkg/output/output.go @@ -84,6 +84,8 @@ type ResultEvent struct { Timestamp time.Time `json:"timestamp"` // Interaction is the full details of interactsh interaction. Interaction *server.Interaction `json:"interaction,omitempty"` + + FileToIndexPosition map[string]int `json:"-"` } // NewStandardWriter creates a new output writer based on user configurations diff --git a/v2/pkg/protocols/file/operators.go b/v2/pkg/protocols/file/operators.go index e7afdaef..674cd09c 100644 --- a/v2/pkg/protocols/file/operators.go +++ b/v2/pkg/protocols/file/operators.go @@ -1,6 +1,8 @@ package file import ( + "bufio" + "strings" "time" "github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors" @@ -100,6 +102,33 @@ func (r *Request) MakeResultEvent(wrapped *output.InternalWrappedEvent) []*outpu data := r.makeResultEventItem(wrapped) results = append(results, data) } + raw, ok := wrapped.InternalEvent["raw"] + if !ok { + return results + } + rawStr, ok := raw.(string) + if !ok { + return results + } + + // Identify the position of match in file using a dirty hack. + for _, result := range results { + for _, extraction := range result.ExtractedResults { + scanner := bufio.NewScanner(strings.NewReader(rawStr)) + + line := 1 + for scanner.Scan() { + if strings.Contains(scanner.Text(), extraction) { + if result.FileToIndexPosition != nil { + result.FileToIndexPosition = make(map[string]int) + } + result.FileToIndexPosition[result.Matched] = line + continue + } + line++ + } + } + } return results } @@ -111,6 +140,7 @@ func (r *Request) makeResultEventItem(wrapped *output.InternalWrappedEvent) *out Type: "file", Path: types.ToString(wrapped.InternalEvent["path"]), Matched: types.ToString(wrapped.InternalEvent["matched"]), + Host: types.ToString(wrapped.InternalEvent["matched"]), ExtractedResults: wrapped.OperatorsResult.OutputExtracts, Timestamp: time.Now(), } diff --git a/v2/pkg/reporting/exporters/sarif/sarif.go b/v2/pkg/reporting/exporters/sarif/sarif.go index 4c222732..1b5d7a5a 100644 --- a/v2/pkg/reporting/exporters/sarif/sarif.go +++ b/v2/pkg/reporting/exporters/sarif/sarif.go @@ -67,6 +67,8 @@ func (i *Exporter) Export(event *output.ResultEvent) error { var templateURL string if strings.HasPrefix(event.TemplatePath, i.home) { templateURL = "https://github.com/projectdiscovery/nuclei-templates/blob/master" + templatePath + } else { + templateURL = "https://github.com/projectdiscovery/nuclei-templates" } var ruleDescription string @@ -82,14 +84,27 @@ func (i *Exporter) Export(event *output.ResultEvent) error { WithHelp(fullDescription). WithHelpURI(templateURL). WithFullDescription(sarif.NewMultiformatMessageString(ruleDescription)) - _ = i.run.AddResult(templateID). + result := i.run.AddResult(templateID). WithMessage(sarif.NewMessage().WithText(event.Host)). - WithLevel(sarifSeverity). - WithLocation(sarif.NewLocation().WithMessage(sarif.NewMessage().WithText(event.Host)).WithPhysicalLocation( + WithLevel(sarifSeverity) + + // Also write file match metadata to file + if event.Type == "file" && event.FileToIndexPosition != nil { + for file, line := range event.FileToIndexPosition { + sc, sl, el, ec := getLimitedLineAndColumns(line) + result.WithLocation(sarif.NewLocation().WithMessage(sarif.NewMessage().WithText(file)).WithPhysicalLocation( + sarif.NewPhysicalLocation(). + WithArtifactLocation(sarif.NewArtifactLocation().WithUri(file)). + WithRegion(sarif.NewRegion().WithStartColumn(sc).WithStartLine(sl).WithEndLine(el).WithEndColumn(ec)), + )) + } + } else { + result.WithLocation(sarif.NewLocation().WithMessage(sarif.NewMessage().WithText(event.Host)).WithPhysicalLocation( sarif.NewPhysicalLocation(). WithArtifactLocation(sarif.NewArtifactLocation().WithUri("README.md")). WithRegion(sarif.NewRegion().WithStartColumn(1).WithStartLine(1).WithEndLine(1).WithEndColumn(1)), )) + } return nil } @@ -112,6 +127,16 @@ func getSarifSeverity(event *output.ResultEvent) string { } } +func getLimitedLineAndColumns(line int) (int, int, int, int) { + var endline = line + + if line-3 != 0 { + endline = line + 6 + line = line - 3 + } + return 1, line, endline, 32 +} + // Close closes the exporter after operation func (i *Exporter) Close() error { i.mutex.Lock()