Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/internal/runner/lazy.go
2070 views
1
package runner
2
3
import (
4
"context"
5
"fmt"
6
"strings"
7
8
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx"
9
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
10
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
11
"github.com/projectdiscovery/nuclei/v3/pkg/output"
12
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
13
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
14
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
15
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/writer"
16
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
17
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
18
"github.com/projectdiscovery/nuclei/v3/pkg/types"
19
"github.com/projectdiscovery/utils/env"
20
"github.com/projectdiscovery/utils/errkit"
21
)
22
23
type AuthLazyFetchOptions struct {
24
TemplateStore *loader.Store
25
ExecOpts *protocols.ExecutorOptions
26
OnError func(error)
27
}
28
29
// GetAuthTmplStore create new loader for loading auth templates
30
func GetAuthTmplStore(opts *types.Options, catalog catalog.Catalog, execOpts *protocols.ExecutorOptions) (*loader.Store, error) {
31
tmpls := []string{}
32
for _, file := range opts.SecretsFile {
33
data, err := authx.GetTemplatePathsFromSecretFile(file)
34
if err != nil {
35
return nil, errkit.Wrap(err, "failed to get template paths from secrets file")
36
}
37
tmpls = append(tmpls, data...)
38
}
39
opts.Templates = tmpls
40
opts.Workflows = nil
41
opts.RemoteTemplateDomainList = nil
42
opts.TemplateURLs = nil
43
opts.WorkflowURLs = nil
44
opts.ExcludedTemplates = nil
45
opts.Tags = nil
46
opts.ExcludeTags = nil
47
opts.IncludeTemplates = nil
48
opts.Authors = nil
49
opts.Severities = nil
50
opts.ExcludeSeverities = nil
51
opts.IncludeTags = nil
52
opts.IncludeIds = nil
53
opts.ExcludeIds = nil
54
opts.Protocols = nil
55
opts.ExcludeProtocols = nil
56
opts.IncludeConditions = nil
57
cfg := loader.NewConfig(opts, catalog, execOpts)
58
cfg.StoreId = loader.AuthStoreId
59
store, err := loader.New(cfg)
60
if err != nil {
61
return nil, errkit.Wrap(err, "failed to initialize dynamic auth templates store")
62
}
63
return store, nil
64
}
65
66
// GetLazyAuthFetchCallback returns a lazy fetch callback for auth secrets
67
func GetLazyAuthFetchCallback(opts *AuthLazyFetchOptions) authx.LazyFetchSecret {
68
return func(d *authx.Dynamic) error {
69
tmpls := opts.TemplateStore.LoadTemplates([]string{d.TemplatePath})
70
if len(tmpls) == 0 {
71
return fmt.Errorf("no templates found for path: %s", d.TemplatePath)
72
}
73
if len(tmpls) > 1 {
74
return fmt.Errorf("multiple templates found for path: %s", d.TemplatePath)
75
}
76
data := map[string]interface{}{}
77
tmpl := tmpls[0]
78
// add args to tmpl here
79
vars := map[string]interface{}{}
80
mainCtx := context.Background()
81
ctx := scan.NewScanContext(mainCtx, contextargs.NewWithInput(mainCtx, d.Input))
82
83
cliVars := map[string]interface{}{}
84
if opts.ExecOpts.Options != nil {
85
// gets variables passed from cli -v and -env-vars
86
cliVars = generators.BuildPayloadFromOptions(opts.ExecOpts.Options)
87
}
88
89
for _, v := range d.Variables {
90
// Check if the template has any env variables and expand them
91
if strings.HasPrefix(v.Value, "$") {
92
env.ExpandWithEnv(&v.Value)
93
}
94
if strings.Contains(v.Value, "{{") {
95
// if variables had value like {{username}}, then replace it with the value from cliVars
96
// variables:
97
// - key: username
98
// value: {{username}}
99
v.Value = replacer.Replace(v.Value, cliVars)
100
}
101
vars[v.Key] = v.Value
102
ctx.Input.Add(v.Key, v.Value)
103
}
104
105
var finalErr error
106
ctx.OnResult = func(e *output.InternalWrappedEvent) {
107
if e == nil {
108
finalErr = fmt.Errorf("no result found for template: %s", d.TemplatePath)
109
return
110
}
111
if !e.HasOperatorResult() {
112
finalErr = fmt.Errorf("no result found for template: %s", d.TemplatePath)
113
return
114
}
115
// dynamic values
116
for k, v := range e.OperatorsResult.DynamicValues {
117
// Iterate through all the values and choose the
118
// largest value as the extracted value
119
for _, value := range v {
120
oldVal, ok := data[k]
121
if !ok || len(value) > len(oldVal.(string)) {
122
data[k] = value
123
}
124
}
125
}
126
// named extractors
127
for k, v := range e.OperatorsResult.Extracts {
128
if len(v) > 0 {
129
data[k] = v[0]
130
}
131
}
132
if len(data) == 0 {
133
if e.OperatorsResult.Matched {
134
finalErr = fmt.Errorf("match found but no (dynamic/extracted) values found for template: %s", d.TemplatePath)
135
} else {
136
finalErr = fmt.Errorf("no match or (dynamic/extracted) values found for template: %s", d.TemplatePath)
137
}
138
}
139
// log result of template in result file/screen
140
_ = writer.WriteResult(e, opts.ExecOpts.Output, opts.ExecOpts.Progress, opts.ExecOpts.IssuesClient)
141
}
142
_, err := tmpl.Executer.ExecuteWithResults(ctx)
143
if err != nil {
144
finalErr = err
145
}
146
// store extracted result in auth context
147
d.Extracted = data
148
if finalErr != nil && opts.OnError != nil {
149
opts.OnError(finalErr)
150
}
151
return finalErr
152
}
153
}
154
155