Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/lib/config.go
2838 views
1
package nuclei
2
3
import (
4
"context"
5
"errors"
6
"os"
7
"time"
8
9
"github.com/projectdiscovery/goflags"
10
"github.com/projectdiscovery/gologger"
11
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
12
"github.com/projectdiscovery/utils/errkit"
13
14
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider"
15
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
16
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
17
"github.com/projectdiscovery/nuclei/v3/pkg/output"
18
"github.com/projectdiscovery/nuclei/v3/pkg/progress"
19
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/hosterrorscache"
20
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
21
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
22
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
23
pkgtypes "github.com/projectdiscovery/nuclei/v3/pkg/types"
24
)
25
26
// TemplateSources contains template sources
27
// which define where to load templates from
28
type TemplateSources struct {
29
Templates []string // template file/directory paths
30
Workflows []string // workflow file/directory paths
31
RemoteTemplates []string // remote template urls
32
RemoteWorkflows []string // remote workflow urls
33
TrustedDomains []string // trusted domains for remote templates/workflows
34
}
35
36
// WithTemplatesOrWorkflows sets templates / workflows to use /load
37
func WithTemplatesOrWorkflows(sources TemplateSources) NucleiSDKOptions {
38
return func(e *NucleiEngine) error {
39
// by default all of these values are empty
40
e.opts.Templates = sources.Templates
41
e.opts.Workflows = sources.Workflows
42
e.opts.TemplateURLs = sources.RemoteTemplates
43
e.opts.WorkflowURLs = sources.RemoteWorkflows
44
e.opts.RemoteTemplateDomainList = append(e.opts.RemoteTemplateDomainList, sources.TrustedDomains...)
45
return nil
46
}
47
}
48
49
// config contains all SDK configuration options
50
type TemplateFilters struct {
51
Severity string // filter by severities (accepts CSV values of info, low, medium, high, critical)
52
ExcludeSeverities string // filter by excluding severities (accepts CSV values of info, low, medium, high, critical)
53
ProtocolTypes string // filter by protocol types
54
ExcludeProtocolTypes string // filter by excluding protocol types
55
Authors []string // fiter by author
56
Tags []string // filter by tags present in template
57
ExcludeTags []string // filter by excluding tags present in template
58
IncludeTags []string // filter by including tags present in template
59
IDs []string // filter by template IDs
60
ExcludeIDs []string // filter by excluding template IDs
61
TemplateCondition []string // DSL condition/ expression
62
}
63
64
// WithTemplateFilters sets template filters and only templates matching the filters will be
65
// loaded and executed
66
func WithTemplateFilters(filters TemplateFilters) NucleiSDKOptions {
67
return func(e *NucleiEngine) error {
68
s := severity.Severities{}
69
if err := s.Set(filters.Severity); err != nil {
70
return err
71
}
72
es := severity.Severities{}
73
if err := es.Set(filters.ExcludeSeverities); err != nil {
74
return err
75
}
76
pt := types.ProtocolTypes{}
77
if err := pt.Set(filters.ProtocolTypes); err != nil {
78
return err
79
}
80
ept := types.ProtocolTypes{}
81
if err := ept.Set(filters.ExcludeProtocolTypes); err != nil {
82
return err
83
}
84
e.opts.Authors = filters.Authors
85
e.opts.Tags = filters.Tags
86
e.opts.ExcludeTags = filters.ExcludeTags
87
e.opts.IncludeTags = filters.IncludeTags
88
e.opts.IncludeIds = filters.IDs
89
e.opts.ExcludeIds = filters.ExcludeIDs
90
e.opts.Severities = s
91
e.opts.ExcludeSeverities = es
92
e.opts.Protocols = pt
93
e.opts.ExcludeProtocols = ept
94
e.opts.IncludeConditions = filters.TemplateCondition
95
return nil
96
}
97
}
98
99
// InteractshOpts contains options for interactsh
100
type InteractshOpts interactsh.Options
101
102
// WithInteractshOptions sets interactsh options
103
func WithInteractshOptions(opts InteractshOpts) NucleiSDKOptions {
104
return func(e *NucleiEngine) error {
105
// WithInteractshOptions can be used when creating ThreadSafeNucleiEngine but not after it's initialized
106
if e.mode == threadSafe && e.interactshOpts != nil {
107
return errkit.Wrap(ErrOptionsNotSupported, "WithInteractshOptions")
108
}
109
optsPtr := &opts
110
e.interactshOpts = (*interactsh.Options)(optsPtr)
111
return nil
112
}
113
}
114
115
// Concurrency options
116
type Concurrency struct {
117
TemplateConcurrency int // number of templates to run concurrently (per host in host-spray mode)
118
HostConcurrency int // number of hosts to scan concurrently (per template in template-spray mode)
119
HeadlessHostConcurrency int // number of hosts to scan concurrently for headless templates (per template in template-spray mode)
120
HeadlessTemplateConcurrency int // number of templates to run concurrently for headless templates (per host in host-spray mode)
121
JavascriptTemplateConcurrency int // number of templates to run concurrently for javascript templates (per host in host-spray mode)
122
TemplatePayloadConcurrency int // max concurrent payloads to run for a template (a good default is 25)
123
ProbeConcurrency int // max concurrent http probes to run (a good default is 50)
124
}
125
126
// WithConcurrency sets concurrency options
127
func WithConcurrency(opts Concurrency) NucleiSDKOptions {
128
return func(e *NucleiEngine) error {
129
// minimum required is 1
130
if opts.TemplateConcurrency <= 0 {
131
return errors.New("template threads must be at least 1")
132
}
133
if opts.HostConcurrency <= 0 {
134
return errors.New("host concurrency must be at least 1")
135
}
136
if opts.HeadlessHostConcurrency <= 0 {
137
return errors.New("headless host concurrency must be at least 1")
138
}
139
if opts.HeadlessTemplateConcurrency <= 0 {
140
return errors.New("headless template threads must be at least 1")
141
}
142
if opts.JavascriptTemplateConcurrency <= 0 {
143
return errors.New("js must be at least 1")
144
}
145
if opts.TemplatePayloadConcurrency <= 0 {
146
return errors.New("payload concurrency must be at least 1")
147
}
148
if opts.ProbeConcurrency <= 0 {
149
return errors.New("probe concurrency must be at least 1")
150
}
151
e.opts.TemplateThreads = opts.TemplateConcurrency
152
e.opts.BulkSize = opts.HostConcurrency
153
e.opts.HeadlessBulkSize = opts.HeadlessHostConcurrency
154
e.opts.HeadlessTemplateThreads = opts.HeadlessTemplateConcurrency
155
e.opts.JsConcurrency = opts.JavascriptTemplateConcurrency
156
e.opts.PayloadConcurrency = opts.TemplatePayloadConcurrency
157
e.opts.ProbeConcurrency = opts.ProbeConcurrency
158
return nil
159
}
160
}
161
162
// WithResponseReadSize sets the maximum size of response to read in bytes.
163
// A value of 0 means no limit. Recommended values: 1MB (1048576) to 10MB (10485760).
164
func WithResponseReadSize(responseReadSize int) NucleiSDKOptions {
165
return func(e *NucleiEngine) error {
166
if responseReadSize < 0 {
167
return errors.New("response read size must be non-negative")
168
}
169
e.opts.ResponseReadSize = responseReadSize
170
return nil
171
}
172
}
173
174
// WithGlobalRateLimit sets global rate (i.e all hosts combined) limit options
175
// Deprecated: will be removed in favour of WithGlobalRateLimitCtx in next release
176
func WithGlobalRateLimit(maxTokens int, duration time.Duration) NucleiSDKOptions {
177
return WithGlobalRateLimitCtx(context.Background(), maxTokens, duration)
178
}
179
180
// WithGlobalRateLimitCtx allows setting a global rate limit for the entire engine
181
func WithGlobalRateLimitCtx(ctx context.Context, maxTokens int, duration time.Duration) NucleiSDKOptions {
182
return func(e *NucleiEngine) error {
183
e.opts.RateLimit = maxTokens
184
e.opts.RateLimitDuration = duration
185
e.rateLimiter = utils.GetRateLimiter(ctx, e.opts.RateLimit, e.opts.RateLimitDuration)
186
return nil
187
}
188
}
189
190
// HeadlessOpts contains options for headless templates
191
type HeadlessOpts struct {
192
PageTimeout int // timeout for page load
193
ShowBrowser bool
194
HeadlessOptions []string
195
UseChrome bool
196
}
197
198
// EnableHeadless allows execution of headless templates
199
//
200
// Warning: enabling headless mode may open up attack surface due to browser
201
// usage and can be prone to exploitation by custom unverified templates if not
202
// properly configured.
203
func EnableHeadlessWithOpts(hopts *HeadlessOpts) NucleiSDKOptions {
204
return func(e *NucleiEngine) error {
205
e.opts.Headless = true
206
if hopts != nil {
207
e.opts.HeadlessOptionalArguments = hopts.HeadlessOptions
208
e.opts.PageTimeout = hopts.PageTimeout
209
e.opts.ShowBrowser = hopts.ShowBrowser
210
e.opts.UseInstalledChrome = hopts.UseChrome
211
}
212
return nil
213
}
214
}
215
216
// StatsOptions
217
type StatsOptions struct {
218
Interval int
219
JSON bool
220
MetricServerPort int
221
}
222
223
// EnableStats enables Stats collection with defined interval(in sec) and callback
224
// Note: callback is executed in a separate goroutine
225
func EnableStatsWithOpts(opts StatsOptions) NucleiSDKOptions {
226
return func(e *NucleiEngine) error {
227
if e.mode == threadSafe {
228
return errkit.Wrap(ErrOptionsNotSupported, "EnableStatsWithOpts")
229
}
230
if opts.Interval == 0 {
231
opts.Interval = 5 //sec
232
}
233
e.opts.StatsInterval = opts.Interval
234
e.enableStats = true
235
e.opts.StatsJSON = opts.JSON
236
e.opts.MetricsPort = opts.MetricServerPort
237
return nil
238
}
239
}
240
241
// VerbosityOptions
242
type VerbosityOptions struct {
243
Verbose bool // show verbose output
244
Silent bool // show only results
245
Debug bool // show debug output
246
DebugRequest bool // show request in debug output
247
DebugResponse bool // show response in debug output
248
ShowVarDump bool // show variable dumps in output
249
}
250
251
// WithVerbosity allows setting verbosity options of (internal) nuclei engine
252
// and does not affect SDK output
253
func WithVerbosity(opts VerbosityOptions) NucleiSDKOptions {
254
return func(e *NucleiEngine) error {
255
if e.mode == threadSafe {
256
return errkit.Wrap(ErrOptionsNotSupported, "WithVerbosity")
257
}
258
e.opts.Verbose = opts.Verbose
259
e.opts.Silent = opts.Silent
260
e.opts.Debug = opts.Debug
261
e.opts.DebugRequests = opts.DebugRequest
262
e.opts.DebugResponse = opts.DebugResponse
263
if opts.ShowVarDump {
264
vardump.EnableVarDump = true
265
}
266
return nil
267
}
268
}
269
270
// NetworkConfig contains network config options
271
// ex: retries , httpx probe , timeout etc
272
type NetworkConfig struct {
273
DisableMaxHostErr bool // Disable max host error optimization (Hosts are not skipped even if they are not responding)
274
Interface string // Interface to use for network scan
275
InternalResolversList []string // Use a list of resolver
276
LeaveDefaultPorts bool // Leave default ports for http/https
277
MaxHostError int // Maximum number of host errors to allow before skipping that host
278
Retries int // Number of retries
279
SourceIP string // SourceIP sets custom source IP address for network requests
280
SystemResolvers bool // Use system resolvers
281
Timeout int // Timeout in seconds
282
TrackError []string // Adds given errors to max host error watchlist
283
}
284
285
// WithNetworkConfig allows setting network config options
286
func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions {
287
return func(e *NucleiEngine) error {
288
// WithNetworkConfig can be used when creating ThreadSafeNucleiEngine but not after it's initialized
289
if e.mode == threadSafe && e.hostErrCache != nil {
290
return errkit.Wrap(ErrOptionsNotSupported, "WithNetworkConfig")
291
}
292
e.opts.NoHostErrors = opts.DisableMaxHostErr
293
e.opts.MaxHostError = opts.MaxHostError
294
if e.opts.ShouldUseHostError() {
295
maxHostError := opts.MaxHostError
296
if e.opts.TemplateThreads > maxHostError {
297
e.Logger.Warning().Msg("The concurrency value is higher than max-host-error")
298
e.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads)
299
maxHostError = e.opts.TemplateThreads
300
e.opts.MaxHostError = maxHostError
301
}
302
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, e.opts.TrackError)
303
cache.SetVerbose(e.opts.Verbose)
304
e.hostErrCache = cache
305
}
306
e.opts.Timeout = opts.Timeout
307
e.opts.Retries = opts.Retries
308
e.opts.LeaveDefaultPorts = opts.LeaveDefaultPorts
309
e.opts.Interface = opts.Interface
310
e.opts.SourceIP = opts.SourceIP
311
e.opts.SystemResolvers = opts.SystemResolvers
312
e.opts.InternalResolversList = opts.InternalResolversList
313
return nil
314
}
315
}
316
317
// WithProxy allows setting proxy options
318
func WithProxy(proxy []string, proxyInternalRequests bool) NucleiSDKOptions {
319
return func(e *NucleiEngine) error {
320
if e.mode == threadSafe {
321
return errkit.Wrap(ErrOptionsNotSupported, "WithProxy")
322
}
323
e.opts.Proxy = proxy
324
e.opts.ProxyInternal = proxyInternalRequests
325
return nil
326
}
327
}
328
329
// WithScanStrategy allows setting scan strategy options
330
func WithScanStrategy(strategy string) NucleiSDKOptions {
331
return func(e *NucleiEngine) error {
332
e.opts.ScanStrategy = strategy
333
return nil
334
}
335
}
336
337
// OutputWriter
338
type OutputWriter output.Writer
339
340
// UseOutputWriter allows setting custom output writer
341
// by default a mock writer is used with user defined callback
342
// if outputWriter is used callback will be ignored
343
func UseOutputWriter(writer OutputWriter) NucleiSDKOptions {
344
return func(e *NucleiEngine) error {
345
if e.mode == threadSafe {
346
return errkit.Wrap(ErrOptionsNotSupported, "UseOutputWriter")
347
}
348
e.customWriter = writer
349
return nil
350
}
351
}
352
353
// StatsWriter
354
type StatsWriter progress.Progress
355
356
// UseStatsWriter allows setting a custom stats writer
357
// which can be used to write stats somewhere (ex: send to webserver etc)
358
func UseStatsWriter(writer StatsWriter) NucleiSDKOptions {
359
return func(e *NucleiEngine) error {
360
if e.mode == threadSafe {
361
return errkit.Wrap(ErrOptionsNotSupported, "UseStatsWriter")
362
}
363
e.customProgress = writer
364
return nil
365
}
366
}
367
368
// WithTemplateUpdateCallback allows setting a callback which will be called
369
// when nuclei templates are outdated
370
// Note: Nuclei-templates are crucial part of nuclei and using outdated templates or nuclei sdk is not recommended
371
// as it may cause unexpected results due to compatibility issues
372
func WithTemplateUpdateCallback(disableTemplatesAutoUpgrade bool, callback func(newVersion string)) NucleiSDKOptions {
373
return func(e *NucleiEngine) error {
374
if e.mode == threadSafe {
375
return errkit.Wrap(ErrOptionsNotSupported, "WithTemplateUpdateCallback")
376
}
377
e.disableTemplatesAutoUpgrade = disableTemplatesAutoUpgrade
378
e.onUpdateAvailableCallback = callback
379
return nil
380
}
381
}
382
383
// WithSandboxOptions allows setting supported sandbox options
384
func WithSandboxOptions(allowLocalFileAccess bool, restrictLocalNetworkAccess bool) NucleiSDKOptions {
385
return func(e *NucleiEngine) error {
386
if e.mode == threadSafe {
387
return errkit.Wrap(ErrOptionsNotSupported, "WithSandboxOptions")
388
}
389
e.opts.AllowLocalFileAccess = allowLocalFileAccess
390
e.opts.RestrictLocalNetworkAccess = restrictLocalNetworkAccess
391
return nil
392
}
393
}
394
395
// EnableCodeTemplates allows loading/executing code protocol templates
396
func EnableCodeTemplates() NucleiSDKOptions {
397
return func(e *NucleiEngine) error {
398
e.opts.EnableCodeTemplates = true
399
e.opts.EnableSelfContainedTemplates = true
400
return nil
401
}
402
}
403
404
// EnableSelfContainedTemplates allows loading/executing self-contained templates
405
func EnableSelfContainedTemplates() NucleiSDKOptions {
406
return func(e *NucleiEngine) error {
407
e.opts.EnableSelfContainedTemplates = true
408
return nil
409
}
410
}
411
412
// EnableGlobalMatchersTemplates allows loading/executing global-matchers templates
413
func EnableGlobalMatchersTemplates() NucleiSDKOptions {
414
return func(e *NucleiEngine) error {
415
e.opts.EnableGlobalMatchersTemplates = true
416
return nil
417
}
418
}
419
420
// DisableTemplateCache disables template caching
421
func DisableTemplateCache() NucleiSDKOptions {
422
return func(e *NucleiEngine) error {
423
e.opts.DoNotCacheTemplates = true
424
return nil
425
}
426
}
427
428
// EnableFileTemplates allows loading/executing file protocol templates
429
func EnableFileTemplates() NucleiSDKOptions {
430
return func(e *NucleiEngine) error {
431
e.opts.EnableFileTemplates = true
432
return nil
433
}
434
}
435
436
// WithHeaders allows setting custom header/cookie to include in all http request in header:value format
437
func WithHeaders(headers []string) NucleiSDKOptions {
438
return func(e *NucleiEngine) error {
439
e.opts.CustomHeaders = headers
440
return nil
441
}
442
}
443
444
// WithVars allows setting custom variables to use in templates/workflows context
445
func WithVars(vars []string) NucleiSDKOptions {
446
// Create a goflags.RuntimeMap
447
runtimeVars := goflags.RuntimeMap{}
448
for _, v := range vars {
449
err := runtimeVars.Set(v)
450
if err != nil {
451
return func(e *NucleiEngine) error {
452
return err
453
}
454
}
455
}
456
457
return func(e *NucleiEngine) error {
458
e.opts.Vars = runtimeVars
459
return nil
460
}
461
}
462
463
// EnablePassiveMode allows enabling passive HTTP response processing mode
464
func EnablePassiveMode() NucleiSDKOptions {
465
return func(e *NucleiEngine) error {
466
e.opts.OfflineHTTP = true
467
e.opts.DisableHTTPProbe = true
468
return nil
469
}
470
}
471
472
// EnableMatcherStatus allows enabling matcher status
473
func EnableMatcherStatus() NucleiSDKOptions {
474
return func(e *NucleiEngine) error {
475
e.opts.MatcherStatus = true
476
return nil
477
}
478
}
479
480
// WithAuthProvider allows setting a custom authprovider implementation
481
func WithAuthProvider(provider authprovider.AuthProvider) NucleiSDKOptions {
482
return func(e *NucleiEngine) error {
483
e.authprovider = provider
484
return nil
485
}
486
}
487
488
// LoadSecretsFromFile allows loading secrets from file
489
func LoadSecretsFromFile(files []string, prefetch bool) NucleiSDKOptions {
490
return func(e *NucleiEngine) error {
491
e.opts.SecretsFile = goflags.StringSlice(files)
492
e.opts.PreFetchSecrets = prefetch
493
return nil
494
}
495
}
496
497
// DASTMode only run DAST templates
498
func DASTMode() NucleiSDKOptions {
499
return func(e *NucleiEngine) error {
500
e.opts.DAST = true
501
return nil
502
}
503
}
504
505
// SignedTemplatesOnly only run signed templates and disabled loading all unsigned templates
506
func SignedTemplatesOnly() NucleiSDKOptions {
507
return func(e *NucleiEngine) error {
508
e.opts.DisableUnsignedTemplates = true
509
return nil
510
}
511
}
512
513
// WithCatalog uses a supplied catalog
514
func WithCatalog(cat catalog.Catalog) NucleiSDKOptions {
515
return func(e *NucleiEngine) error {
516
e.catalog = cat
517
return nil
518
}
519
}
520
521
// DisableUpdateCheck disables nuclei update check
522
func DisableUpdateCheck() NucleiSDKOptions {
523
return func(e *NucleiEngine) error {
524
DefaultConfig.DisableUpdateCheck()
525
return nil
526
}
527
}
528
529
// WithResumeFile allows setting a resume file
530
func WithResumeFile(file string) NucleiSDKOptions {
531
return func(e *NucleiEngine) error {
532
e.opts.Resume = file
533
return nil
534
}
535
}
536
537
// WithLogger allows setting a shared gologger instance
538
func WithLogger(logger *gologger.Logger) NucleiSDKOptions {
539
return func(e *NucleiEngine) error {
540
e.Logger = logger
541
if e.opts != nil {
542
e.opts.Logger = logger
543
}
544
if e.executerOpts != nil {
545
e.executerOpts.Logger = logger
546
}
547
return nil
548
}
549
}
550
551
// WithOptions sets all options at once
552
func WithOptions(opts *pkgtypes.Options) NucleiSDKOptions {
553
return func(e *NucleiEngine) error {
554
e.opts = opts
555
return nil
556
}
557
}
558
559
// WithTemporaryDirectory allows setting a parent directory for SDK-managed temporary files.
560
// A temporary directory will be created inside the provided directory and cleaned up on engine close.
561
// If not set, a temporary directory will be automatically created in the system temp location.
562
// The parent directory is assumed to exist.
563
func WithTemporaryDirectory(parentDir string) NucleiSDKOptions {
564
return func(e *NucleiEngine) error {
565
tmpDir, err := os.MkdirTemp(parentDir, "nuclei-tmp-*")
566
if err != nil {
567
return err
568
}
569
e.tmpDir = tmpDir
570
return nil
571
}
572
}
573
574