2021-02-02 12:10:47 +05:30
|
|
|
package format
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
|
2021-08-05 16:22:28 +03:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
2021-02-02 12:10:47 +05:30
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Summary returns a formatted built one line summary of the event
|
2021-02-26 13:13:11 +05:30
|
|
|
func Summary(event *output.ResultEvent) string {
|
|
|
|
|
template := GetMatchedTemplate(event)
|
2021-02-02 12:10:47 +05:30
|
|
|
|
|
|
|
|
builder := &strings.Builder{}
|
|
|
|
|
builder.WriteString("[")
|
|
|
|
|
builder.WriteString(template)
|
|
|
|
|
builder.WriteString("] [")
|
2021-07-13 11:12:03 +03:00
|
|
|
builder.WriteString(types.ToString(event.Info.SeverityHolder))
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("] ")
|
2021-07-12 17:20:01 +03:00
|
|
|
builder.WriteString(types.ToString(event.Info.Name))
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString(" found on ")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.Host)
|
2021-02-02 12:10:47 +05:30
|
|
|
data := builder.String()
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MarkdownDescription formats a short description of the generated
|
|
|
|
|
// event by the nuclei scanner in Markdown format.
|
2021-08-03 15:05:13 +03:00
|
|
|
func MarkdownDescription(event *output.ResultEvent) string { // TODO remove the code duplication: format.go <-> jira.go
|
2021-02-26 13:13:11 +05:30
|
|
|
template := GetMatchedTemplate(event)
|
2021-02-02 12:10:47 +05:30
|
|
|
builder := &bytes.Buffer{}
|
|
|
|
|
builder.WriteString("**Details**: **")
|
|
|
|
|
builder.WriteString(template)
|
|
|
|
|
builder.WriteString("** ")
|
2021-08-05 16:22:28 +03:00
|
|
|
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString(" matched at ")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.Host)
|
2021-08-05 16:22:28 +03:00
|
|
|
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("\n\n**Protocol**: ")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(strings.ToUpper(event.Type))
|
2021-08-05 16:22:28 +03:00
|
|
|
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("\n\n**Full URL**: ")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.Matched)
|
2021-08-05 16:22:28 +03:00
|
|
|
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("\n\n**Timestamp**: ")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
|
2021-07-12 17:20:01 +03:00
|
|
|
|
2021-08-05 16:22:28 +03:00
|
|
|
builder.WriteString("\n\n**Template Information**\n\n| Key | Value |\n|---|---|\n")
|
|
|
|
|
builder.WriteString(toMarkdownTableString(&event.Info))
|
2021-07-12 17:20:01 +03:00
|
|
|
|
2021-03-22 14:03:05 +05:30
|
|
|
if event.Request != "" {
|
2021-03-22 15:00:26 +05:30
|
|
|
builder.WriteString("\n**Request**\n\n```http\n")
|
2021-03-22 14:03:05 +05:30
|
|
|
builder.WriteString(event.Request)
|
2021-03-22 15:00:26 +05:30
|
|
|
builder.WriteString("\n```\n")
|
2021-03-22 14:03:05 +05:30
|
|
|
}
|
|
|
|
|
if event.Response != "" {
|
2021-03-22 15:00:26 +05:30
|
|
|
builder.WriteString("\n**Response**\n\n```http\n")
|
2021-03-22 14:03:05 +05:30
|
|
|
// If the response is larger than 5 kb, truncate it before writing.
|
|
|
|
|
if len(event.Response) > 5*1024 {
|
|
|
|
|
builder.WriteString(event.Response[:5*1024])
|
|
|
|
|
builder.WriteString(".... Truncated ....")
|
|
|
|
|
} else {
|
|
|
|
|
builder.WriteString(event.Response)
|
|
|
|
|
}
|
2021-06-06 17:38:39 +05:30
|
|
|
builder.WriteString("\n```\n")
|
2021-03-22 14:03:05 +05:30
|
|
|
}
|
2021-02-02 12:10:47 +05:30
|
|
|
|
2021-02-26 13:13:11 +05:30
|
|
|
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 {
|
2021-06-06 17:38:39 +05:30
|
|
|
builder.WriteString("\n**Extra Information**\n\n")
|
2021-02-26 13:13:11 +05:30
|
|
|
if len(event.ExtractedResults) > 0 {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("**Extracted results**:\n\n")
|
2021-02-26 13:13:11 +05:30
|
|
|
for _, v := range event.ExtractedResults {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("- ")
|
|
|
|
|
builder.WriteString(v)
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
2021-02-26 13:13:11 +05:30
|
|
|
if len(event.Metadata) > 0 {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("**Metadata**:\n\n")
|
2021-02-26 13:13:11 +05:30
|
|
|
for k, v := range event.Metadata {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString("- ")
|
|
|
|
|
builder.WriteString(k)
|
|
|
|
|
builder.WriteString(": ")
|
|
|
|
|
builder.WriteString(types.ToString(v))
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-03 14:08:09 +05:30
|
|
|
if event.Interaction != nil {
|
|
|
|
|
builder.WriteString("**Interaction Data**\n---\n")
|
|
|
|
|
builder.WriteString(event.Interaction.Protocol)
|
|
|
|
|
if event.Interaction.QType != "" {
|
|
|
|
|
builder.WriteString(" (")
|
|
|
|
|
builder.WriteString(event.Interaction.QType)
|
|
|
|
|
builder.WriteString(")")
|
|
|
|
|
}
|
|
|
|
|
builder.WriteString(" Interaction from ")
|
|
|
|
|
builder.WriteString(event.Interaction.RemoteAddress)
|
|
|
|
|
builder.WriteString(" at ")
|
|
|
|
|
builder.WriteString(event.Interaction.UniqueID)
|
|
|
|
|
|
|
|
|
|
if event.Interaction.RawRequest != "" {
|
|
|
|
|
builder.WriteString("\n\n**Interaction Request**\n\n```\n")
|
|
|
|
|
builder.WriteString(event.Interaction.RawRequest)
|
|
|
|
|
builder.WriteString("\n```\n")
|
|
|
|
|
}
|
|
|
|
|
if event.Interaction.RawResponse != "" {
|
|
|
|
|
builder.WriteString("\n**Interaction Response**\n\n```\n")
|
|
|
|
|
builder.WriteString(event.Interaction.RawResponse)
|
|
|
|
|
builder.WriteString("\n```\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-07-12 17:20:01 +03:00
|
|
|
|
2021-08-03 14:51:34 +03:00
|
|
|
reference := event.Info.Reference
|
|
|
|
|
if !reference.IsEmpty() {
|
2021-06-05 23:00:59 +05:30
|
|
|
builder.WriteString("\nReference: \n")
|
|
|
|
|
|
2021-08-03 15:05:13 +03:00
|
|
|
/*TODO couldn't the following code replace the logic below?
|
|
|
|
|
referenceSlice := reference.ToSlice()
|
|
|
|
|
for i, item := range referenceSlice {
|
|
|
|
|
builder.WriteString("- ")
|
|
|
|
|
builder.WriteString(item)
|
|
|
|
|
if len(referenceSlice)-1 != i {
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
2021-08-03 14:51:34 +03:00
|
|
|
switch value := reference.Value.(type) {
|
2021-06-05 23:00:59 +05:30
|
|
|
case string:
|
2021-07-12 17:20:01 +03:00
|
|
|
if !strings.HasPrefix(value, "-") {
|
2021-06-06 01:04:20 +05:30
|
|
|
builder.WriteString("- ")
|
|
|
|
|
}
|
2021-07-12 17:20:01 +03:00
|
|
|
builder.WriteString(value)
|
2021-06-05 23:00:59 +05:30
|
|
|
case []interface{}:
|
2021-07-12 17:20:01 +03:00
|
|
|
slice := types.ToStringSlice(value)
|
2021-06-05 23:00:59 +05:30
|
|
|
for i, item := range slice {
|
|
|
|
|
builder.WriteString("- ")
|
|
|
|
|
builder.WriteString(item)
|
|
|
|
|
if len(slice)-1 != i {
|
|
|
|
|
builder.WriteString("\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-03 14:08:09 +05:30
|
|
|
|
2021-03-22 14:36:08 +05:30
|
|
|
builder.WriteString("\n---\nGenerated by [Nuclei](https://github.com/projectdiscovery/nuclei)")
|
2021-02-02 12:10:47 +05:30
|
|
|
data := builder.String()
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetMatchedTemplate returns the matched template from a result event
|
2021-02-26 13:13:11 +05:30
|
|
|
func GetMatchedTemplate(event *output.ResultEvent) string {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder := &strings.Builder{}
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.TemplateID)
|
|
|
|
|
if event.MatcherName != "" {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString(":")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.MatcherName)
|
2021-02-02 12:10:47 +05:30
|
|
|
}
|
2021-02-26 13:13:11 +05:30
|
|
|
if event.ExtractorName != "" {
|
2021-02-02 12:10:47 +05:30
|
|
|
builder.WriteString(":")
|
2021-02-26 13:13:11 +05:30
|
|
|
builder.WriteString(event.ExtractorName)
|
2021-02-02 12:10:47 +05:30
|
|
|
}
|
|
|
|
|
template := builder.String()
|
|
|
|
|
return template
|
|
|
|
|
}
|
2021-08-05 16:22:28 +03:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
TODO remove and reuse the duplicated logic below jira.go <-> format.go
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
func toMarkdownTableString(templateInfo *model.Info) string {
|
|
|
|
|
fields := map[string]string{
|
|
|
|
|
"Name": templateInfo.Name,
|
|
|
|
|
"Authors": sliceToString(templateInfo.Authors),
|
|
|
|
|
"Tags": sliceToString(templateInfo.Tags),
|
|
|
|
|
"Description": templateInfo.Description,
|
|
|
|
|
"Severity": templateInfo.SeverityHolder.Severity.String(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
builder := &bytes.Buffer{}
|
|
|
|
|
for k, v := range fields {
|
|
|
|
|
builder.WriteString(fmt.Sprintf("| %s | %s |\n", k, v))
|
|
|
|
|
}
|
|
|
|
|
return builder.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func sliceToString(stringSlice model.StringSlice) string {
|
|
|
|
|
return strings.Join(stringSlice.ToSlice(), ", ")
|
|
|
|
|
}
|