Skip to content

Commit

Permalink
Merge pull request #799 from projectdiscovery/loader-fix
Browse files Browse the repository at this point in the history
[wip] Nuclei Templates Loader Rewrite
  • Loading branch information
Ice3man543 authored Jul 2, 2021
2 parents f61d420 + 3dbf51f commit c731e7f
Show file tree
Hide file tree
Showing 20 changed files with 815 additions and 495 deletions.
6 changes: 5 additions & 1 deletion v2/cmd/nuclei/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ based on templates offering massive extensibility and ease of use.`)
set.StringSliceVarP(&options.Templates, "templates", "t", []string{}, "Templates to run, supports single and multiple templates using directory.")
set.StringSliceVarP(&options.Workflows, "workflows", "w", []string{}, "Workflows to run for nuclei")
set.StringSliceVarP(&options.ExcludedTemplates, "exclude", "et", []string{}, "Templates to exclude, supports single and multiple templates using directory.")
set.StringSliceVarP(&options.Severity, "severity", "impact", []string{}, "Templates to run based on severity, supports single and multiple severity.")
set.StringSliceVarP(&options.Severity, "severity", "impact", []string{}, "Templates to run based on severity")
set.StringSliceVar(&options.Author, "author", []string{}, "Templates to run based on author")
set.StringSliceVar(&options.IncludeTemplates, "include-templates", []string{}, "Templates to force run even if they are in denylist")
set.StringSliceVar(&options.IncludeTags, "include-tags", []string{}, "Tags to force run even if they are in denylist")
set.StringVarP(&options.Targets, "list", "l", "", "List of URLs to run templates on")
set.StringVarP(&options.Output, "output", "o", "", "File to write output to (optional)")
set.StringVar(&options.ProxyURL, "proxy-url", "", "URL of the proxy server")
Expand Down Expand Up @@ -92,6 +95,7 @@ based on templates offering massive extensibility and ease of use.`)
set.IntVar(&options.InteractionsEviction, "interactions-eviction", 60, "Number of seconds to wait before evicting requests from cache")
set.IntVar(&options.InteractionsPollDuration, "interactions-poll-duration", 5, "Number of seconds before each interaction poll request")
set.IntVar(&options.InteractionsColldownPeriod, "interactions-cooldown-period", 5, "Extra time for interaction polling before exiting")
set.BoolVar(&options.VerboseVerbose, "vv", false, "Display Extra Verbose Information")
_ = set.Parse()

if cfgFile != "" {
Expand Down
20 changes: 13 additions & 7 deletions v2/internal/runner/banner.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package runner

import "github.com/projectdiscovery/gologger"
import (
"fmt"

const banner = `
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
)

var banner string

func init() {
banner = fmt.Sprintf(`
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v2.3.8
`

// Version is the current version of nuclei
const Version = `2.3.8`
/_/ /_/\__,_/\___/_/\___/_/ %s
`, config.Version)
}

// showBanner is used to show the banner to the user
func showBanner() {
Expand Down
126 changes: 0 additions & 126 deletions v2/internal/runner/config.go
Original file line number Diff line number Diff line change
@@ -1,127 +1 @@
package runner

import (
"os"
"path"
"regexp"
"time"

jsoniter "github.com/json-iterator/go"
"github.com/projectdiscovery/gologger"
"gopkg.in/yaml.v2"
)

// nucleiConfig contains some configuration options for nuclei
type nucleiConfig struct {
TemplatesDirectory string `json:"templates-directory,omitempty"`
CurrentVersion string `json:"current-version,omitempty"`
LastChecked time.Time `json:"last-checked,omitempty"`
IgnoreURL string `json:"ignore-url,omitempty"`
NucleiVersion string `json:"nuclei-version,omitempty"`
LastCheckedIgnore time.Time `json:"last-checked-ignore,omitempty"`
// IgnorePaths ignores all the paths listed unless specified manually
IgnorePaths []string `json:"ignore-paths,omitempty"`
}

// nucleiConfigFilename is the filename of nuclei configuration file.
const nucleiConfigFilename = ".templates-config.json"

var reVersion = regexp.MustCompile(`\d+\.\d+\.\d+`)

// readConfiguration reads the nuclei configuration file from disk.
func readConfiguration() (*nucleiConfig, error) {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
configDir := path.Join(home, "/.config", "/nuclei")
_ = os.MkdirAll(configDir, os.ModePerm)

templatesConfigFile := path.Join(configDir, nucleiConfigFilename)
file, err := os.Open(templatesConfigFile)
if err != nil {
return nil, err
}
defer file.Close()

config := &nucleiConfig{}
err = jsoniter.NewDecoder(file).Decode(config)
if err != nil {
return nil, err
}
return config, nil
}

// readConfiguration reads the nuclei configuration file from disk.
func (r *Runner) writeConfiguration(config *nucleiConfig) error {
home, err := os.UserHomeDir()
if err != nil {
return err
}
configDir := path.Join(home, "/.config", "/nuclei")
_ = os.MkdirAll(configDir, os.ModePerm)

if config.IgnoreURL == "" {
config.IgnoreURL = "https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/master/.nuclei-ignore"
}
config.LastChecked = time.Now()
config.LastCheckedIgnore = time.Now()
config.NucleiVersion = Version
templatesConfigFile := path.Join(configDir, nucleiConfigFilename)
file, err := os.OpenFile(templatesConfigFile, os.O_WRONLY|os.O_CREATE, 0777)
if err != nil {
return err
}
defer file.Close()

err = jsoniter.NewEncoder(file).Encode(config)
if err != nil {
return err
}
return nil
}

const nucleiIgnoreFile = ".nuclei-ignore"

type ignoreFile struct {
Tags []string `yaml:"tags"`
Files []string `yaml:"files"`
}

// readNucleiIgnoreFile reads the nuclei ignore file marking it in map
func (r *Runner) readNucleiIgnoreFile() {
file, err := os.Open(r.getIgnoreFilePath())
if err != nil {
gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n", err)
return
}
defer file.Close()

ignore := &ignoreFile{}
if err := yaml.NewDecoder(file).Decode(ignore); err != nil {
gologger.Error().Msgf("Could not parse nuclei-ignore file: %s\n", err)
return
}
r.options.ExcludeTags = append(r.options.ExcludeTags, ignore.Tags...)
r.templatesConfig.IgnorePaths = append(r.templatesConfig.IgnorePaths, ignore.Files...)
}

// getIgnoreFilePath returns the ignore file path for the runner
func (r *Runner) getIgnoreFilePath() string {
var defIgnoreFilePath string

home, err := os.UserHomeDir()
if err == nil {
configDir := path.Join(home, "/.config", "/nuclei")
_ = os.MkdirAll(configDir, os.ModePerm)

defIgnoreFilePath = path.Join(configDir, nucleiIgnoreFile)
return defIgnoreFilePath
}
cwd, err := os.Getwd()
if err != nil {
return defIgnoreFilePath
}
cwdIgnoreFilePath := path.Join(cwd, nucleiIgnoreFile)
return cwdIgnoreFilePath
}
12 changes: 3 additions & 9 deletions v2/internal/runner/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/formatter"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
)
Expand All @@ -26,11 +27,11 @@ func ParseOptions(options *types.Options) {
showBanner()

if options.Version {
gologger.Info().Msgf("Current Version: %s\n", Version)
gologger.Info().Msgf("Current Version: %s\n", config.Version)
os.Exit(0)
}
if options.TemplatesVersion {
config, err := readConfiguration()
config, err := config.ReadConfiguration()
if err != nil {
gologger.Fatal().Msgf("Could not read template configuration: %s\n", err)
}
Expand Down Expand Up @@ -80,13 +81,6 @@ func validateOptions(options *types.Options) error {
return errors.New("both verbose and silent mode specified")
}

if !options.TemplateList {
// Check if a list of templates was provided and it exists
if len(options.Templates) == 0 && !options.NewTemplates && len(options.Workflows) == 0 && len(options.Tags) == 0 && !options.UpdateTemplates {
return errors.New("no template/templates provided")
}
}

// Validate proxy options if provided
err := validateProxyURL(options.ProxyURL, "invalid http proxy format (It should be http://username:password@host:port)")
if err != nil {
Expand Down
Loading

0 comments on commit c731e7f

Please sign in to comment.