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