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