nuclei/pkg/input/provider/http/multiformat.go
HD Moore 0c7bade615 Remove singletons from Nuclei engine (continuation of #6210) (#6296)
* introducing execution id

* wip

* .

* adding separate execution context id

* lint

* vet

* fixing pg dialers

* test ignore

* fixing loader FD limit

* test

* fd fix

* wip: remove CloseProcesses() from dev merge

* wip: fix merge issue

* protocolstate: stop memguarding on last dialer delete

* avoid data race in dialers.RawHTTPClient

* use shared logger and avoid race conditions

* use shared logger and avoid race conditions

* go mod

* patch executionId into compiled template cache

* clean up comment in Parse

* go mod update

* bump echarts

* address merge issues

* fix use of gologger

* switch cmd/nuclei to options.Logger

* address merge issues with go.mod

* go vet: address copy of lock with new Copy function

* fixing tests

* disable speed control

* fix nil ExecuterOptions

* removing deprecated code

* fixing result print

* default logger

* cli default logger

* filter warning from results

* fix performance test

* hardcoding path

* disable upload

* refactor(runner): uses `Warning` instead of `Print` for `pdcpUploadErrMsg`

Signed-off-by: Dwi Siswanto <git@dw1.io>

* Revert "disable upload"

This reverts commit 114fbe6663361bf41cf8b2645fd2d57083d53682.

* Revert "hardcoding path"

This reverts commit cf12ca800e0a0e974bd9fd4826a24e51547f7c00.

---------

Signed-off-by: Dwi Siswanto <git@dw1.io>
Co-authored-by: Mzack9999 <mzack9999@protonmail.com>
Co-authored-by: Dwi Siswanto <git@dw1.io>
Co-authored-by: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com>
2025-08-02 15:56:04 +05:30

159 lines
4.5 KiB
Go

package http
import (
"bytes"
"io"
"os"
"strings"
"github.com/pkg/errors"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/burp"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/json"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/openapi"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/swagger"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/yaml"
"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
)
// HttpMultiFormatOptions contains options for the http input provider
type HttpMultiFormatOptions struct {
// Options for the http input provider
Options formats.InputFormatOptions
// InputFile is the file containing the input
InputFile string
// InputMode is the mode of input
InputMode string
// optional input reader
InputContents string
}
// HttpInputProvider implements an input provider for nuclei that loads
// inputs from multiple formats like burp, openapi, postman,proxify, etc.
type HttpInputProvider struct {
format formats.Format
inputData []byte
inputFile string
count int64
}
// NewHttpInputProvider creates a new input provider for nuclei from a file
// or an input string
//
// The first preference is given to input file if provided
// otherwise it will use the input string
func NewHttpInputProvider(opts *HttpMultiFormatOptions) (*HttpInputProvider, error) {
var format formats.Format
for _, provider := range providersList {
if provider.Name() == opts.InputMode {
format = provider
}
}
if format == nil {
return nil, errors.Errorf("invalid input mode %s", opts.InputMode)
}
format.SetOptions(opts.Options)
// Do a first pass over the input to identify any errors
// and get the count of the input file as well
count := int64(0)
var inputFile *os.File
var inputReader io.Reader
if opts.InputFile != "" {
file, err := os.Open(opts.InputFile)
if err != nil {
return nil, errors.Wrap(err, "could not open input file")
}
inputFile = file
inputReader = file
} else {
inputReader = strings.NewReader(opts.InputContents)
}
defer func() {
if inputFile != nil {
_ = inputFile.Close()
}
}()
data, err := io.ReadAll(inputReader)
if err != nil {
return nil, errors.Wrap(err, "could not read input file")
}
if len(data) == 0 {
return nil, errors.New("input file is empty")
}
parseErr := format.Parse(bytes.NewReader(data), func(request *types.RequestResponse) bool {
count++
return false
}, opts.InputFile)
if parseErr != nil {
return nil, errors.Wrap(parseErr, "could not parse input file")
}
return &HttpInputProvider{format: format, inputData: data, inputFile: opts.InputFile, count: count}, nil
}
// Count returns the number of items for input provider
func (i *HttpInputProvider) Count() int64 {
return i.count
}
// Iterate over all inputs in order
func (i *HttpInputProvider) Iterate(callback func(value *contextargs.MetaInput) bool) {
err := i.format.Parse(bytes.NewReader(i.inputData), func(request *types.RequestResponse) bool {
metaInput := contextargs.NewMetaInput()
metaInput.ReqResp = request
metaInput.Input = request.URL.String()
return callback(metaInput)
}, i.inputFile)
if err != nil {
gologger.Warning().Msgf("Could not parse input file while iterating: %s\n", err)
}
}
// Set adds item to input provider
// No-op for this provider
func (i *HttpInputProvider) Set(_ string, value string) {}
// SetWithProbe adds item to input provider with http probing
// No-op for this provider
func (i *HttpInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error {
return nil
}
// SetWithExclusions adds item to input provider if it doesn't match any of the exclusions
// No-op for this provider
func (i *HttpInputProvider) SetWithExclusions(_ string, value string) error {
return nil
}
// InputType returns the type of input provider
func (i *HttpInputProvider) InputType() string {
return "MultiFormatInputProvider"
}
// Close closes the input provider and cleans up any resources
// No-op for this provider
func (i *HttpInputProvider) Close() {}
// Supported Providers
var providersList = []formats.Format{
burp.New(),
json.New(),
yaml.New(),
openapi.New(),
swagger.New(),
}
// SupportedFormats returns the list of supported formats in comma-separated
// manner
func SupportedFormats() string {
var formats []string
for _, provider := range providersList {
formats = append(formats, provider.Name())
}
return strings.Join(formats, ", ")
}