diff --git a/README.md b/README.md index 8dab51cf0..8d2529258 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ TEMPLATES: -validate validate the passed templates to nuclei -nss, -no-strict-syntax Disable strict syntax check on templates -tl list all available templates + -td displays the template contents FILTERING: -a, -author string[] templates to run based on authors (comma-separated, file) diff --git a/README_CN.md b/README_CN.md index 195b54b8c..be23e8e60 100644 --- a/README_CN.md +++ b/README_CN.md @@ -108,6 +108,7 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板 -validate 验证通过的模板 -nss, -no-strict-syntax 禁用模板的严格检查 -tl 列出所有可用的模板 + -td 显示模板内容 过滤: -a, -author string[] 执行指定作者的模板(逗号分隔,文件) diff --git a/README_KR.md b/README_KR.md index 91d9adeb4..ff3688948 100644 --- a/README_KR.md +++ b/README_KR.md @@ -106,6 +106,7 @@ TEMPLATES: -wu, -workflow-url string[] 실행할 워크플로 URL 목록(쉼표로 구분된 파일) -validate nuclei로 전달된 템플릿 검증 -tl 사용 가능한 모든 템플릿 목록 + -td 템플릿 내용 표시 FILTERING: -a, -author string[] 작성자를 기준으로 실행할 템플릿(쉼표로 구분된 파일) diff --git a/v2/cmd/nuclei/main.go b/v2/cmd/nuclei/main.go index 94f806af2..3788050cb 100644 --- a/v2/cmd/nuclei/main.go +++ b/v2/cmd/nuclei/main.go @@ -140,6 +140,7 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.StringSliceVarP(&options.WorkflowURLs, "workflow-url", "wu", []string{}, "list of workflow urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions), flagSet.BoolVar(&options.Validate, "validate", false, "validate the passed templates to nuclei"), flagSet.BoolVarP(&options.NoStrictSyntax, "no-strict-syntax", "nss", false, "disable strict syntax check on templates"), + flagSet.BoolVarP(&options.TemplateDisplay, "template-display", "td", false, "displays the templates content"), flagSet.BoolVar(&options.TemplateList, "tl", false, "list all available templates"), flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"api.nuclei.sh"}, "allowed domain list to load remote templates from"), ) diff --git a/v2/go.mod b/v2/go.mod index 8c0e550cf..0144e33a8 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -86,6 +86,7 @@ require ( ) require ( + github.com/dlclark/regexp2 v1.4.0 // indirect github.com/projectdiscovery/folderutil v0.0.0-20220215113126-add60a1e8e08 // indirect github.com/projectdiscovery/sliceutil v0.0.1 // indirect gopkg.in/djherbis/times.v1 v1.3.0 // indirect @@ -202,6 +203,7 @@ require ( github.com/Microsoft/go-winio v0.4.16 // indirect github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect + github.com/alecthomas/chroma v0.10.0 github.com/emirpasic/gods v1.12.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.3.1 // indirect diff --git a/v2/go.sum b/v2/go.sum index e1c967047..0cb324263 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -78,6 +78,8 @@ github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= +github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/jsonschema v0.0.0-20210818095345-1014919a589c/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 h1:NjwIgLQlD46o79bheVG4SCdRnnOz4XtgUN1WABX5DLA= github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= @@ -192,6 +194,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= diff --git a/v2/internal/runner/runner.go b/v2/internal/runner/runner.go index cf5ed5131..bcefb50a3 100644 --- a/v2/internal/runner/runner.go +++ b/v2/internal/runner/runner.go @@ -421,7 +421,7 @@ func (r *Runner) RunEnumeration() error { } } // list all templates - if r.options.TemplateList { + if r.options.TemplateList || r.options.TemplateDisplay { r.listAvailableStoreTemplates(store) os.Exit(0) } diff --git a/v2/internal/runner/templates.go b/v2/internal/runner/templates.go index 72afb5c45..862d299f3 100644 --- a/v2/internal/runner/templates.go +++ b/v2/internal/runner/templates.go @@ -1,10 +1,15 @@ package runner import ( - "github.com/projectdiscovery/nuclei/v2/pkg/catalog/loader" + "bytes" + "io/ioutil" "path/filepath" "strings" + "github.com/alecthomas/chroma/quick" + "github.com/logrusorgru/aurora" + "github.com/projectdiscovery/nuclei/v2/pkg/catalog/loader" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v2/pkg/parsers" "github.com/projectdiscovery/nuclei/v2/pkg/templates" @@ -17,36 +22,73 @@ func (r *Runner) logAvailableTemplate(tplPath string) { if err != nil { gologger.Error().Msgf("Could not parse file '%s': %s\n", tplPath, err) } else { - gologger.Print().Msgf("%s\n", templates.TemplateLogMessage(t.ID, - types.ToString(t.Info.Name), - t.Info.Authors.ToSlice(), - t.Info.SeverityHolder.Severity)) + r.verboseTemplate(t) } } +// log available templates for verbose (-vv) +func (r *Runner) verboseTemplate(tpl *templates.Template) { + gologger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID, + types.ToString(tpl.Info.Name), + tpl.Info.Authors.ToSlice(), + tpl.Info.SeverityHolder.Severity)) +} + func (r *Runner) listAvailableStoreTemplates(store *loader.Store) { gologger.Print().Msgf( "\nListing available v.%s nuclei templates for %s", r.templatesConfig.TemplateVersion, r.templatesConfig.TemplatesDirectory, ) - extraFlags := r.options.Templates != nil || r.options.Authors != nil || - r.options.Tags != nil || len(r.options.ExcludeTags) > 3 || - r.options.IncludeTags != nil || r.options.IncludeIds != nil || - r.options.ExcludeIds != nil || r.options.IncludeTemplates != nil || - r.options.ExcludedTemplates != nil || r.options.ExcludeMatchers != nil || - r.options.Severities != nil || r.options.ExcludeSeverities != nil || - r.options.Protocols != nil || r.options.ExcludeProtocols != nil || - r.options.IncludeConditions != nil || r.options.TemplateList - for _, tl := range store.Templates() { - if extraFlags { - path := strings.TrimPrefix(tl.Path, r.templatesConfig.TemplatesDirectory+string(filepath.Separator)) - gologger.Silent().Msgf("%s\n", path) + for _, tpl := range store.Templates() { + if hasExtraFlags(r.options) { + if r.options.TemplateDisplay { + colorize := !r.options.NoColor + + path := tpl.Path + tplBody, err := ioutil.ReadFile(path) + if err != nil { + gologger.Error().Msgf("Could not read the template %s: %s", path, err) + continue + } + + if colorize { + path = aurora.Cyan(tpl.Path).String() + tplBody, err = r.highlightTemplate(&tplBody) + if err != nil { + gologger.Error().Msgf("Could not hihglight the template %s: %s", tpl.Path, err) + continue + } + + } + gologger.Silent().Msgf("Template: %s\n\n%s", path, tplBody) + } else { + gologger.Silent().Msgf("%s\n", strings.TrimPrefix(tpl.Path, r.templatesConfig.TemplatesDirectory+string(filepath.Separator))) + } } else { - gologger.Print().Msgf("%s\n", templates.TemplateLogMessage(tl.ID, - types.ToString(tl.Info.Name), - tl.Info.Authors.ToSlice(), - tl.Info.SeverityHolder.Severity)) + r.verboseTemplate(tpl) } } } + +func (r *Runner) highlightTemplate(body *[]byte) ([]byte, error) { + var buf bytes.Buffer + // YAML lexer, true color terminar formatter and monokai style + err := quick.Highlight(&buf, string(*body), "yaml", "terminal16m", "monokai") + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func hasExtraFlags(options *types.Options) bool { + return options.Templates != nil || options.Authors != nil || + options.Tags != nil || len(options.ExcludeTags) > 3 || + options.IncludeTags != nil || options.IncludeIds != nil || + options.ExcludeIds != nil || options.IncludeTemplates != nil || + options.ExcludedTemplates != nil || options.ExcludeMatchers != nil || + options.Severities != nil || options.ExcludeSeverities != nil || + options.Protocols != nil || options.ExcludeProtocols != nil || + options.IncludeConditions != nil || options.TemplateList +} diff --git a/v2/pkg/catalog/loader/loader.go b/v2/pkg/catalog/loader/loader.go index 9fa390033..4351d654f 100644 --- a/v2/pkg/catalog/loader/loader.go +++ b/v2/pkg/catalog/loader/loader.go @@ -2,6 +2,7 @@ package loader import ( "os" + "sort" "github.com/pkg/errors" "github.com/projectdiscovery/gologger" @@ -284,6 +285,11 @@ func (store *Store) LoadTemplates(templatesList []string) []*templates.Template gologger.Warning().Msgf("Could not load template %s: %s\n", templatePath, err) } } + + sort.SliceStable(loadedTemplates, func(i, j int) bool { + return loadedTemplates[i].Path < loadedTemplates[j].Path + }) + return loadedTemplates } diff --git a/v2/pkg/types/types.go b/v2/pkg/types/types.go index b2360f534..3632cb6ab 100644 --- a/v2/pkg/types/types.go +++ b/v2/pkg/types/types.go @@ -202,6 +202,8 @@ type Options struct { EnableProgressBar bool // TemplatesVersion shows the templates installed version TemplatesVersion bool + // TemplateDisplay displays the template contents + TemplateDisplay bool // TemplateList lists available templates TemplateList bool // HangMonitor enables nuclei hang monitoring