Path: blob/dev/pkg/input/provider/http/multiformat.go
2072 views
package http12import (3"bytes"4"io"5"os"6"strings"78"github.com/pkg/errors"9"github.com/projectdiscovery/gologger"10"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"11"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/burp"12"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/json"13"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/openapi"14"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/swagger"15"github.com/projectdiscovery/nuclei/v3/pkg/input/formats/yaml"16"github.com/projectdiscovery/nuclei/v3/pkg/input/types"17"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"18)1920// HttpMultiFormatOptions contains options for the http input provider21type HttpMultiFormatOptions struct {22// Options for the http input provider23Options formats.InputFormatOptions24// InputFile is the file containing the input25InputFile string26// InputMode is the mode of input27InputMode string2829// optional input reader30InputContents string31}3233// HttpInputProvider implements an input provider for nuclei that loads34// inputs from multiple formats like burp, openapi, postman,proxify, etc.35type HttpInputProvider struct {36format formats.Format37inputData []byte38inputFile string39count int6440}4142// NewHttpInputProvider creates a new input provider for nuclei from a file43// or an input string44//45// The first preference is given to input file if provided46// otherwise it will use the input string47func NewHttpInputProvider(opts *HttpMultiFormatOptions) (*HttpInputProvider, error) {48var format formats.Format49for _, provider := range providersList {50if provider.Name() == opts.InputMode {51format = provider52}53}54if format == nil {55return nil, errors.Errorf("invalid input mode %s", opts.InputMode)56}57format.SetOptions(opts.Options)58// Do a first pass over the input to identify any errors59// and get the count of the input file as well60count := int64(0)61var inputFile *os.File62var inputReader io.Reader63if opts.InputFile != "" {64file, err := os.Open(opts.InputFile)65if err != nil {66return nil, errors.Wrap(err, "could not open input file")67}68inputFile = file69inputReader = file70} else {71inputReader = strings.NewReader(opts.InputContents)72}73defer func() {74if inputFile != nil {75_ = inputFile.Close()76}77}()7879data, err := io.ReadAll(inputReader)80if err != nil {81return nil, errors.Wrap(err, "could not read input file")82}83if len(data) == 0 {84return nil, errors.New("input file is empty")85}8687parseErr := format.Parse(bytes.NewReader(data), func(request *types.RequestResponse) bool {88count++89return false90}, opts.InputFile)91if parseErr != nil {92return nil, errors.Wrap(parseErr, "could not parse input file")93}94return &HttpInputProvider{format: format, inputData: data, inputFile: opts.InputFile, count: count}, nil95}9697// Count returns the number of items for input provider98func (i *HttpInputProvider) Count() int64 {99return i.count100}101102// Iterate over all inputs in order103func (i *HttpInputProvider) Iterate(callback func(value *contextargs.MetaInput) bool) {104err := i.format.Parse(bytes.NewReader(i.inputData), func(request *types.RequestResponse) bool {105metaInput := contextargs.NewMetaInput()106metaInput.ReqResp = request107metaInput.Input = request.URL.String()108return callback(metaInput)109}, i.inputFile)110if err != nil {111gologger.Warning().Msgf("Could not parse input file while iterating: %s\n", err)112}113}114115// Set adds item to input provider116// No-op for this provider117func (i *HttpInputProvider) Set(_ string, value string) {}118119// SetWithProbe adds item to input provider with http probing120// No-op for this provider121func (i *HttpInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error {122return nil123}124125// SetWithExclusions adds item to input provider if it doesn't match any of the exclusions126// No-op for this provider127func (i *HttpInputProvider) SetWithExclusions(_ string, value string) error {128return nil129}130131// InputType returns the type of input provider132func (i *HttpInputProvider) InputType() string {133return "MultiFormatInputProvider"134}135136// Close closes the input provider and cleans up any resources137// No-op for this provider138func (i *HttpInputProvider) Close() {}139140// Supported Providers141var providersList = []formats.Format{142burp.New(),143json.New(),144yaml.New(),145openapi.New(),146swagger.New(),147}148149// SupportedFormats returns the list of supported formats in comma-separated150// manner151func SupportedFormats() string {152var formats []string153for _, provider := range providersList {154formats = append(formats, provider.Name())155}156return strings.Join(formats, ", ")157}158159160