Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/input/provider/http/multiformat.go
2072 views
1
package http
2
3
import (
4
"bytes"
5
"io"
6
"os"
7
"strings"
8
9
"github.com/pkg/errors"
10
"github.com/projectdiscovery/gologger"
11
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"
12
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/burp"
13
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/json"
14
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/openapi"
15
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/swagger"
16
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/yaml"
17
"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
18
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
19
)
20
21
// HttpMultiFormatOptions contains options for the http input provider
22
type HttpMultiFormatOptions struct {
23
// Options for the http input provider
24
Options formats.InputFormatOptions
25
// InputFile is the file containing the input
26
InputFile string
27
// InputMode is the mode of input
28
InputMode string
29
30
// optional input reader
31
InputContents string
32
}
33
34
// HttpInputProvider implements an input provider for nuclei that loads
35
// inputs from multiple formats like burp, openapi, postman,proxify, etc.
36
type HttpInputProvider struct {
37
format formats.Format
38
inputData []byte
39
inputFile string
40
count int64
41
}
42
43
// NewHttpInputProvider creates a new input provider for nuclei from a file
44
// or an input string
45
//
46
// The first preference is given to input file if provided
47
// otherwise it will use the input string
48
func NewHttpInputProvider(opts *HttpMultiFormatOptions) (*HttpInputProvider, error) {
49
var format formats.Format
50
for _, provider := range providersList {
51
if provider.Name() == opts.InputMode {
52
format = provider
53
}
54
}
55
if format == nil {
56
return nil, errors.Errorf("invalid input mode %s", opts.InputMode)
57
}
58
format.SetOptions(opts.Options)
59
// Do a first pass over the input to identify any errors
60
// and get the count of the input file as well
61
count := int64(0)
62
var inputFile *os.File
63
var inputReader io.Reader
64
if opts.InputFile != "" {
65
file, err := os.Open(opts.InputFile)
66
if err != nil {
67
return nil, errors.Wrap(err, "could not open input file")
68
}
69
inputFile = file
70
inputReader = file
71
} else {
72
inputReader = strings.NewReader(opts.InputContents)
73
}
74
defer func() {
75
if inputFile != nil {
76
_ = inputFile.Close()
77
}
78
}()
79
80
data, err := io.ReadAll(inputReader)
81
if err != nil {
82
return nil, errors.Wrap(err, "could not read input file")
83
}
84
if len(data) == 0 {
85
return nil, errors.New("input file is empty")
86
}
87
88
parseErr := format.Parse(bytes.NewReader(data), func(request *types.RequestResponse) bool {
89
count++
90
return false
91
}, opts.InputFile)
92
if parseErr != nil {
93
return nil, errors.Wrap(parseErr, "could not parse input file")
94
}
95
return &HttpInputProvider{format: format, inputData: data, inputFile: opts.InputFile, count: count}, nil
96
}
97
98
// Count returns the number of items for input provider
99
func (i *HttpInputProvider) Count() int64 {
100
return i.count
101
}
102
103
// Iterate over all inputs in order
104
func (i *HttpInputProvider) Iterate(callback func(value *contextargs.MetaInput) bool) {
105
err := i.format.Parse(bytes.NewReader(i.inputData), func(request *types.RequestResponse) bool {
106
metaInput := contextargs.NewMetaInput()
107
metaInput.ReqResp = request
108
metaInput.Input = request.URL.String()
109
return callback(metaInput)
110
}, i.inputFile)
111
if err != nil {
112
gologger.Warning().Msgf("Could not parse input file while iterating: %s\n", err)
113
}
114
}
115
116
// Set adds item to input provider
117
// No-op for this provider
118
func (i *HttpInputProvider) Set(_ string, value string) {}
119
120
// SetWithProbe adds item to input provider with http probing
121
// No-op for this provider
122
func (i *HttpInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error {
123
return nil
124
}
125
126
// SetWithExclusions adds item to input provider if it doesn't match any of the exclusions
127
// No-op for this provider
128
func (i *HttpInputProvider) SetWithExclusions(_ string, value string) error {
129
return nil
130
}
131
132
// InputType returns the type of input provider
133
func (i *HttpInputProvider) InputType() string {
134
return "MultiFormatInputProvider"
135
}
136
137
// Close closes the input provider and cleans up any resources
138
// No-op for this provider
139
func (i *HttpInputProvider) Close() {}
140
141
// Supported Providers
142
var providersList = []formats.Format{
143
burp.New(),
144
json.New(),
145
yaml.New(),
146
openapi.New(),
147
swagger.New(),
148
}
149
150
// SupportedFormats returns the list of supported formats in comma-separated
151
// manner
152
func SupportedFormats() string {
153
var formats []string
154
for _, provider := range providersList {
155
formats = append(formats, provider.Name())
156
}
157
return strings.Join(formats, ", ")
158
}
159
160