mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 19:25:26 +00:00
* Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
369 lines
25 KiB
Go
369 lines
25 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"runtime"
|
|
"runtime/pprof"
|
|
"time"
|
|
|
|
"github.com/projectdiscovery/goflags"
|
|
"github.com/projectdiscovery/gologger"
|
|
"github.com/projectdiscovery/interactsh/pkg/client"
|
|
"github.com/projectdiscovery/nuclei/v2/internal/runner"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators/common/dsl"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/uncover"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http"
|
|
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/utils/monitor"
|
|
fileutil "github.com/projectdiscovery/utils/file"
|
|
)
|
|
|
|
var (
|
|
cfgFile string
|
|
memProfile string // optional profile file path
|
|
options = &types.Options{}
|
|
)
|
|
|
|
func main() {
|
|
if err := runner.ConfigureOptions(); err != nil {
|
|
gologger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
|
}
|
|
flagSet := readConfig()
|
|
configPath, _ := flagSet.GetConfigFilePath()
|
|
|
|
if options.ListDslSignatures {
|
|
gologger.Info().Msgf("The available custom DSL functions are:")
|
|
fmt.Println(dsl.GetPrintableDslFunctionSignatures(options.NoColor))
|
|
return
|
|
}
|
|
|
|
// Profiling related code
|
|
if memProfile != "" {
|
|
f, err := os.Create(memProfile)
|
|
if err != nil {
|
|
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
|
|
}
|
|
old := runtime.MemProfileRate
|
|
runtime.MemProfileRate = 4096
|
|
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
|
|
|
|
defer func() {
|
|
_ = pprof.Lookup("heap").WriteTo(f, 0)
|
|
f.Close()
|
|
runtime.MemProfileRate = old
|
|
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
|
|
}()
|
|
}
|
|
|
|
runner.ParseOptions(options)
|
|
options.ConfigPath = configPath
|
|
|
|
if options.HangMonitor {
|
|
cancel := monitor.NewStackMonitor(10 * time.Second)
|
|
defer cancel()
|
|
}
|
|
|
|
nucleiRunner, err := runner.New(options)
|
|
if err != nil {
|
|
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
|
|
}
|
|
if nucleiRunner == nil {
|
|
return
|
|
}
|
|
|
|
// Setup graceful exits
|
|
resumeFileName := types.DefaultResumeFilePath()
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, os.Interrupt)
|
|
go func() {
|
|
for range c {
|
|
gologger.Info().Msgf("CTRL+C pressed: Exiting\n")
|
|
nucleiRunner.Close()
|
|
if options.ShouldSaveResume() {
|
|
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
|
err := nucleiRunner.SaveResumeConfig(resumeFileName)
|
|
if err != nil {
|
|
gologger.Error().Msgf("Couldn't create resume file: %s\n", err)
|
|
}
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
|
|
if err := nucleiRunner.RunEnumeration(); err != nil {
|
|
if options.Validate {
|
|
gologger.Fatal().Msgf("Could not validate templates: %s\n", err)
|
|
} else {
|
|
gologger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
|
}
|
|
}
|
|
nucleiRunner.Close()
|
|
// on successful execution remove the resume file in case it exists
|
|
if fileutil.FileExists(resumeFileName) {
|
|
os.Remove(resumeFileName)
|
|
}
|
|
}
|
|
|
|
func readConfig() *goflags.FlagSet {
|
|
|
|
flagSet := goflags.NewFlagSet()
|
|
flagSet.SetDescription(`Nuclei is a fast, template based vulnerability scanner focusing
|
|
on extensive configurability, massive extensibility and ease of use.`)
|
|
|
|
/* TODO Important: The defined default values, especially for slice/array types are NOT DEFAULT VALUES, but rather implicit values to which the user input is appended.
|
|
This can be very confusing and should be addressed
|
|
*/
|
|
|
|
flagSet.CreateGroup("input", "Target",
|
|
flagSet.StringSliceVarP(&options.Targets, "target", "u", []string{}, "target URLs/hosts to scan", goflags.StringSliceOptions),
|
|
flagSet.StringVarP(&options.TargetsFilePath, "list", "l", "", "path to file containing a list of target URLs/hosts to scan (one per line)"),
|
|
flagSet.StringVar(&options.Resume, "resume", "", "resume scan using resume.cfg (clustering will be disabled)"),
|
|
flagSet.BoolVarP(&options.ScanAllIPs, "scan-all-ips", "sa", false, "scan all the IP's associated with dns record"),
|
|
flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", []string{""}, "IP version to scan of hostname (4,6) - (default 4)", goflags.CommaSeparatedStringSliceOptions),
|
|
)
|
|
|
|
flagSet.CreateGroup("templates", "Templates",
|
|
flagSet.BoolVarP(&options.NewTemplates, "new-templates", "nt", false, "run only new templates added in latest nuclei-templates release"),
|
|
flagSet.StringSliceVarP(&options.NewTemplatesWithVersion, "new-templates-version", "ntv", []string{}, "run new templates added in specific version", goflags.CommaSeparatedStringSliceOptions),
|
|
flagSet.BoolVarP(&options.AutomaticScan, "automatic-scan", "as", false, "automatic web scan using wappalyzer technology detection to tags mapping"),
|
|
flagSet.StringSliceVarP(&options.Templates, "templates", "t", []string{}, "list of template or template directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.TemplateURLs, "template-url", "tu", []string{}, "list of template urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.Workflows, "workflows", "w", []string{}, "list of workflow or workflow directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
|
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"),
|
|
)
|
|
|
|
flagSet.CreateGroup("filters", "Filtering",
|
|
flagSet.StringSliceVarP(&options.Authors, "author", "a", []string{}, "templates to run based on authors (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
|
flagSet.StringSliceVar(&options.Tags, "tags", []string{}, "templates to run based on tags (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.ExcludeTags, "exclude-tags", "etags", []string{}, "templates to exclude based on tags (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.IncludeTags, "include-tags", "itags", []string{}, "tags to be executed even if they are excluded either by default or configuration", goflags.FileNormalizedStringSliceOptions), // TODO show default deny list
|
|
flagSet.StringSliceVarP(&options.IncludeIds, "template-id", "id", []string{}, "templates to run based on template ids (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.ExcludeIds, "exclude-id", "eid", []string{}, "templates to exclude based on template ids (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.IncludeTemplates, "include-templates", "it", []string{}, "templates to be executed even if they are excluded either by default or configuration", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.ExcludedTemplates, "exclude-templates", "et", []string{}, "template or template directory to exclude (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.ExcludeMatchers, "exclude-matchers", "em", []string{}, "template matchers to exclude in result", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.VarP(&options.Severities, "severity", "s", fmt.Sprintf("templates to run based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
|
flagSet.VarP(&options.ExcludeSeverities, "exclude-severity", "es", fmt.Sprintf("templates to exclude based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
|
flagSet.VarP(&options.Protocols, "type", "pt", fmt.Sprintf("templates to run based on protocol type. Possible values: %s", templateTypes.GetSupportedProtocolTypes())),
|
|
flagSet.VarP(&options.ExcludeProtocols, "exclude-type", "ept", fmt.Sprintf("templates to exclude based on protocol type. Possible values: %s", templateTypes.GetSupportedProtocolTypes())),
|
|
flagSet.StringSliceVarP(&options.IncludeConditions, "template-condition", "tc", nil, "templates to run based on expression condition", goflags.StringSliceOptions),
|
|
)
|
|
|
|
flagSet.CreateGroup("output", "Output",
|
|
flagSet.StringVarP(&options.Output, "output", "o", "", "output file to write found issues/vulnerabilities"),
|
|
flagSet.BoolVarP(&options.StoreResponse, "store-resp", "sresp", false, "store all request/response passed through nuclei to output directory"),
|
|
flagSet.StringVarP(&options.StoreResponseDir, "store-resp-dir", "srd", runner.DefaultDumpTrafficOutputFolder, "store all request/response passed through nuclei to custom directory"),
|
|
flagSet.BoolVar(&options.Silent, "silent", false, "display findings only"),
|
|
flagSet.BoolVarP(&options.NoColor, "no-color", "nc", false, "disable output content coloring (ANSI escape codes)"),
|
|
flagSet.BoolVar(&options.JSON, "json", false, "write output in JSONL(ines) format"),
|
|
flagSet.BoolVarP(&options.JSONRequests, "include-rr", "irr", false, "include request/response pairs in the JSONL output (for findings only)"),
|
|
flagSet.BoolVarP(&options.NoMeta, "no-meta", "nm", false, "disable printing result metadata in cli output"),
|
|
flagSet.BoolVarP(&options.Timestamp, "timestamp", "ts", false, "enables printing timestamp in cli output"),
|
|
flagSet.StringVarP(&options.ReportingDB, "report-db", "rdb", "", "nuclei reporting database (always use this to persist report data)"),
|
|
flagSet.BoolVarP(&options.MatcherStatus, "matcher-status", "ms", false, "display match failure status"),
|
|
flagSet.StringVarP(&options.MarkdownExportDirectory, "markdown-export", "me", "", "directory to export results in markdown format"),
|
|
flagSet.StringVarP(&options.SarifExport, "sarif-export", "se", "", "file to export results in SARIF format"),
|
|
)
|
|
|
|
flagSet.CreateGroup("configs", "Configurations",
|
|
flagSet.StringVar(&cfgFile, "config", "", "path to the nuclei configuration file"),
|
|
flagSet.BoolVarP(&options.FollowRedirects, "follow-redirects", "fr", false, "enable following redirects for http templates"),
|
|
flagSet.BoolVarP(&options.FollowHostRedirects, "follow-host-redirects", "fhr", false, "follow redirects on the same host"),
|
|
flagSet.IntVarP(&options.MaxRedirects, "max-redirects", "mr", 10, "max number of redirects to follow for http templates"),
|
|
flagSet.BoolVarP(&options.DisableRedirects, "disable-redirects", "dr", false, "disable redirects for http templates"),
|
|
flagSet.StringVarP(&options.ReportingConfig, "report-config", "rc", "", "nuclei reporting module configuration file"), // TODO merge into the config file or rename to issue-tracking
|
|
flagSet.StringSliceVarP(&options.CustomHeaders, "header", "H", []string{}, "custom header/cookie to include in all http request in header:value format (cli, file)", goflags.FileStringSliceOptions),
|
|
flagSet.RuntimeMapVarP(&options.Vars, "var", "V", []string{}, "custom vars in key=value format"),
|
|
flagSet.StringVarP(&options.ResolversFile, "resolvers", "r", "", "file containing resolver list for nuclei"),
|
|
flagSet.BoolVarP(&options.SystemResolvers, "system-resolvers", "sr", false, "use system DNS resolving as error fallback"),
|
|
flagSet.BoolVarP(&options.DisableClustering, "disable-clustering", "dc", false, "disable clustering of requests"),
|
|
flagSet.BoolVar(&options.OfflineHTTP, "passive", false, "enable passive HTTP response processing mode"),
|
|
flagSet.BoolVarP(&options.ForceAttemptHTTP2, "force-http2", "fh2", false, "force http2 connection on requests"),
|
|
flagSet.BoolVarP(&options.EnvironmentVariables, "env-vars", "ev", false, "enable environment variables to be used in template"),
|
|
flagSet.StringVarP(&options.ClientCertFile, "client-cert", "cc", "", "client certificate file (PEM-encoded) used for authenticating against scanned hosts"),
|
|
flagSet.StringVarP(&options.ClientKeyFile, "client-key", "ck", "", "client key file (PEM-encoded) used for authenticating against scanned hosts"),
|
|
flagSet.StringVarP(&options.ClientCAFile, "client-ca", "ca", "", "client certificate authority file (PEM-encoded) used for authenticating against scanned hosts"),
|
|
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
|
|
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13"),
|
|
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
|
|
flagSet.BoolVar(&options.Sandbox, "sandbox", false, "sandbox nuclei for safe templates execution"),
|
|
flagSet.StringVarP(&options.Interface, "interface", "i", "", "network interface to use for network scan"),
|
|
flagSet.StringVarP(&options.AttackType, "attack-type", "at", "", "type of payload combinations to perform (batteringram,pitchfork,clusterbomb)"),
|
|
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
|
|
flagSet.StringVar(&options.CustomConfigDir, "config-directory", "", "override the default config path ($home/.config)"),
|
|
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 10*1024*1024, "max response size to read in bytes"),
|
|
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", 1*1024*1024, "max response size to read in bytes"),
|
|
)
|
|
|
|
flagSet.CreateGroup("interactsh", "interactsh",
|
|
flagSet.StringVarP(&options.InteractshURL, "interactsh-server", "iserver", "", fmt.Sprintf("interactsh server url for self-hosted instance (default: %s)", client.DefaultOptions.ServerURL)),
|
|
flagSet.StringVarP(&options.InteractshToken, "interactsh-token", "itoken", "", "authentication token for self-hosted interactsh server"),
|
|
flagSet.IntVar(&options.InteractionsCacheSize, "interactions-cache-size", 5000, "number of requests to keep in the interactions cache"),
|
|
flagSet.IntVar(&options.InteractionsEviction, "interactions-eviction", 60, "number of seconds to wait before evicting requests from cache"),
|
|
flagSet.IntVar(&options.InteractionsPollDuration, "interactions-poll-duration", 5, "number of seconds to wait before each interaction poll request"),
|
|
flagSet.IntVar(&options.InteractionsCoolDownPeriod, "interactions-cooldown-period", 5, "extra time for interaction polling before exiting"),
|
|
flagSet.BoolVarP(&options.NoInteractsh, "no-interactsh", "ni", false, "disable interactsh server for OAST testing, exclude OAST based templates"),
|
|
)
|
|
|
|
flagSet.CreateGroup("uncover", "Uncover",
|
|
flagSet.BoolVarP(&options.Uncover, "uncover", "uc", false, "enable uncover engine"),
|
|
flagSet.StringSliceVarP(&options.UncoverQuery, "uncover-query", "uq", []string{}, "uncover search query", goflags.FileStringSliceOptions),
|
|
flagSet.StringSliceVarP(&options.UncoverEngine, "uncover-engine", "ue", []string{}, fmt.Sprintf("uncover search engine (%s) (default shodan)", uncover.GetUncoverSupportedAgents()), goflags.FileStringSliceOptions),
|
|
flagSet.StringVarP(&options.UncoverField, "uncover-field", "uf", "ip:port", "uncover fields to return (ip,port,host)"),
|
|
flagSet.IntVarP(&options.UncoverLimit, "uncover-limit", "ul", 100, "uncover results to return"),
|
|
flagSet.IntVarP(&options.UncoverDelay, "uncover-delay", "ucd", 1, "delay between uncover query requests in seconds (0 to disable)"),
|
|
)
|
|
|
|
flagSet.CreateGroup("rate-limit", "Rate-Limit",
|
|
flagSet.IntVarP(&options.RateLimit, "rate-limit", "rl", 150, "maximum number of requests to send per second"),
|
|
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute"),
|
|
flagSet.IntVarP(&options.BulkSize, "bulk-size", "bs", 25, "maximum number of hosts to be analyzed in parallel per template"),
|
|
flagSet.IntVarP(&options.TemplateThreads, "concurrency", "c", 25, "maximum number of templates to be executed in parallel"),
|
|
flagSet.IntVarP(&options.HeadlessBulkSize, "headless-bulk-size", "hbs", 10, "maximum number of headless hosts to be analyzed in parallel per template"),
|
|
flagSet.IntVarP(&options.HeadlessTemplateThreads, "headless-concurrency", "headc", 10, "maximum number of headless templates to be executed in parallel"),
|
|
)
|
|
|
|
flagSet.CreateGroup("optimization", "Optimizations",
|
|
flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"),
|
|
flagSet.IntVar(&options.Retries, "retries", 1, "number of times to retry a failed request"),
|
|
flagSet.BoolVarP(&options.LeaveDefaultPorts, "leave-default-ports", "ldp", false, "leave default HTTP/HTTPS ports (eg. host:80,host:443)"),
|
|
flagSet.IntVarP(&options.MaxHostError, "max-host-error", "mhe", 30, "max errors for a host before skipping from scan"),
|
|
flagSet.BoolVar(&options.Project, "project", false, "use a project folder to avoid sending same request multiple times"),
|
|
flagSet.StringVar(&options.ProjectPath, "project-path", os.TempDir(), "set a specific project path"),
|
|
flagSet.BoolVarP(&options.StopAtFirstMatch, "stop-at-first-match", "spm", false, "stop processing HTTP requests after the first match (may break template/workflow logic)"),
|
|
flagSet.BoolVar(&options.Stream, "stream", false, "stream mode - start elaborating without sorting the input"),
|
|
flagSet.DurationVarP(&options.InputReadTimeout, "input-read-timeout", "irt", time.Duration(3*time.Minute), "timeout on input read"),
|
|
flagSet.BoolVarP(&options.DisableHTTPProbe, "no-httpx", "nh", false, "disable httpx probing for non-url input"),
|
|
flagSet.BoolVar(&options.DisableStdin, "no-stdin", false, "disable stdin processing"),
|
|
)
|
|
|
|
flagSet.CreateGroup("headless", "Headless",
|
|
flagSet.BoolVar(&options.Headless, "headless", false, "enable templates that require headless browser support (root user on Linux will disable sandbox)"),
|
|
flagSet.IntVar(&options.PageTimeout, "page-timeout", 20, "seconds to wait for each page in headless mode"),
|
|
flagSet.BoolVarP(&options.ShowBrowser, "show-browser", "sb", false, "show the browser on the screen when running templates with headless mode"),
|
|
flagSet.BoolVarP(&options.UseInstalledChrome, "system-chrome", "sc", false, "use local installed Chrome browser instead of nuclei installed"),
|
|
flagSet.BoolVarP(&options.ShowActions, "list-headless-action", "lha", false, "list available headless actions"),
|
|
)
|
|
|
|
flagSet.CreateGroup("debug", "Debug",
|
|
flagSet.BoolVar(&options.Debug, "debug", false, "show all requests and responses"),
|
|
flagSet.BoolVarP(&options.DebugRequests, "debug-req", "dreq", false, "show all sent requests"),
|
|
flagSet.BoolVarP(&options.DebugResponse, "debug-resp", "dresp", false, "show all received responses"),
|
|
flagSet.StringSliceVarP(&options.Proxy, "proxy", "p", []string{}, "list of http/socks5 proxy to use (comma separated or file input)", goflags.FileCommaSeparatedStringSliceOptions),
|
|
flagSet.BoolVarP(&options.ProxyInternal, "proxy-internal", "pi", false, "proxy all internal requests"),
|
|
flagSet.BoolVarP(&options.ListDslSignatures, "list-dsl-function", "ldf", false, "list all supported DSL function signatures"),
|
|
flagSet.StringVarP(&options.TraceLogFile, "trace-log", "tlog", "", "file to write sent requests trace log"),
|
|
flagSet.StringVarP(&options.ErrorLogFile, "error-log", "elog", "", "file to write sent requests error log"),
|
|
flagSet.BoolVar(&options.Version, "version", false, "show nuclei version"),
|
|
flagSet.BoolVarP(&options.HangMonitor, "hang-monitor", "hm", false, "enable nuclei hang monitoring"),
|
|
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
|
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
|
|
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
|
flagSet.BoolVarP(&options.ShowVarDump, "show-var-dump", "svd", false, "show variables dump for debugging"),
|
|
flagSet.BoolVarP(&options.EnablePprof, "enable-pprof", "ep", false, "enable pprof debugging server"),
|
|
flagSet.BoolVarP(&options.TemplatesVersion, "templates-version", "tv", false, "shows the version of the installed nuclei-templates"),
|
|
flagSet.BoolVarP(&options.HealthCheck, "health-check", "hc", false, "run diagnostic check up"),
|
|
)
|
|
|
|
flagSet.CreateGroup("update", "Update",
|
|
flagSet.BoolVarP(&options.UpdateNuclei, "update", "un", false, "update nuclei engine to the latest released version"),
|
|
flagSet.BoolVarP(&options.UpdateTemplates, "update-templates", "ut", false, "update nuclei-templates to latest released version"),
|
|
flagSet.StringVarP(&options.TemplatesDirectory, "update-template-dir", "ud", "", "custom directory to install / update nuclei-templates"),
|
|
flagSet.BoolVarP(&options.NoUpdateTemplates, "disable-update-check", "duc", false, "disable automatic nuclei/templates update check"),
|
|
)
|
|
|
|
flagSet.CreateGroup("stats", "Statistics",
|
|
flagSet.BoolVar(&options.EnableProgressBar, "stats", false, "display statistics about the running scan"),
|
|
flagSet.BoolVarP(&options.StatsJSON, "stats-json", "sj", false, "write statistics data to an output file in JSONL(ines) format"),
|
|
flagSet.IntVarP(&options.StatsInterval, "stats-interval", "si", 5, "number of seconds to wait between showing a statistics update"),
|
|
flagSet.BoolVarP(&options.Metrics, "metrics", "m", false, "expose nuclei metrics on a port"),
|
|
flagSet.IntVarP(&options.MetricsPort, "metrics-port", "mp", 9092, "port to expose nuclei metrics on"),
|
|
)
|
|
|
|
flagSet.CreateGroup("cloud", "Cloud",
|
|
flagSet.BoolVar(&options.Cloud, "cloud", false, "run scan on nuclei cloud"),
|
|
flagSet.StringVarP(&options.AddDatasource, "add-datasource", "ads", "", "add specified data source (s3,github)"),
|
|
flagSet.StringVarP(&options.AddTarget, "add-target", "atr", "", "add target(s) to cloud"),
|
|
flagSet.StringVarP(&options.AddTemplate, "add-template", "atm", "", "add template(s) to cloud"),
|
|
flagSet.BoolVarP(&options.ScanList, "list-scan", "lsn", false, "list previous cloud scans"),
|
|
flagSet.BoolVarP(&options.ListTargets, "list-target", "ltr", false, "list cloud target by id"),
|
|
flagSet.BoolVarP(&options.ListTemplates, "list-template", "ltm", false, "list cloud template by id"),
|
|
flagSet.BoolVarP(&options.ListDatasources, "list-datasource", "lds", false, "list cloud datasource by id"),
|
|
flagSet.StringVarP(&options.DeleteScan, "delete-scan", "dsn", "", "delete cloud scan by id"),
|
|
flagSet.StringVarP(&options.RemoveTarget, "delete-target", "dtr", "", "delete target(s) from cloud"),
|
|
flagSet.StringVarP(&options.RemoveTemplate, "delete-template", "dtm", "", "delete template(s) from cloud"),
|
|
flagSet.StringVarP(&options.RemoveDatasource, "delete-datasource", "dds", "", "delete specified data source"),
|
|
flagSet.StringVarP(&options.GetTarget, "get-target", "gtr", "", "get target content by id"),
|
|
flagSet.StringVarP(&options.GetTemplate, "get-template", "gtm", "", "get template content by id"),
|
|
flagSet.BoolVarP(&options.NoStore, "no-store", "nos", false, "disable scan/output storage on cloud"),
|
|
flagSet.StringVarP(&options.ScanOutput, "scan-output", "sno", "", "display scan output by scan id"),
|
|
flagSet.BoolVar(&options.NoTables, "no-tables", false, "do not display pretty-printed tables"),
|
|
flagSet.IntVar(&options.OutputLimit, "limit", 100, "limit the number of output to display"),
|
|
)
|
|
|
|
_ = flagSet.Parse()
|
|
|
|
if options.LeaveDefaultPorts {
|
|
http.LeaveDefaultPorts = true
|
|
}
|
|
if options.CustomConfigDir != "" {
|
|
originalIgnorePath := config.GetIgnoreFilePath()
|
|
config.SetCustomConfigDirectory(options.CustomConfigDir)
|
|
configPath := filepath.Join(options.CustomConfigDir, "config.yaml")
|
|
ignoreFile := filepath.Join(options.CustomConfigDir, ".nuclei-ignore")
|
|
if !fileutil.FileExists(ignoreFile) {
|
|
_ = fileutil.CopyFile(originalIgnorePath, ignoreFile)
|
|
}
|
|
readConfigFile := func() error {
|
|
if err := flagSet.MergeConfigFile(configPath); err != nil && !errors.Is(err, io.EOF) {
|
|
defaultConfigPath, _ := flagSet.GetConfigFilePath()
|
|
err = fileutil.CopyFile(defaultConfigPath, configPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return errors.New("reload the config file")
|
|
}
|
|
return nil
|
|
}
|
|
if err := readConfigFile(); err != nil {
|
|
_ = readConfigFile()
|
|
}
|
|
}
|
|
if cfgFile != "" {
|
|
if err := flagSet.MergeConfigFile(cfgFile); err != nil {
|
|
gologger.Fatal().Msgf("Could not read config: %s\n", err)
|
|
}
|
|
cfgFileFolder := filepath.Dir(cfgFile)
|
|
if err := config.OverrideIgnoreFilePath(cfgFileFolder); err != nil {
|
|
gologger.Warning().Msgf("Could not read ignore file from custom path: %s\n", err)
|
|
}
|
|
}
|
|
cleanupOldResumeFiles()
|
|
return flagSet
|
|
}
|
|
|
|
func cleanupOldResumeFiles() {
|
|
root, err := config.GetConfigDir()
|
|
if err != nil {
|
|
return
|
|
}
|
|
filter := fileutil.FileFilters{
|
|
OlderThan: 24 * time.Hour * 10, // cleanup on the 10th day
|
|
Prefix: "resume-",
|
|
}
|
|
_ = fileutil.DeleteFilesOlderThan(root, filter)
|
|
}
|