diff --git a/v2/cmd/nuclei/main.go b/v2/cmd/nuclei/main.go index 0c0eb93f..072c380e 100644 --- a/v2/cmd/nuclei/main.go +++ b/v2/cmd/nuclei/main.go @@ -132,6 +132,8 @@ on extensive configurability, massive extensibility and ease of use.`) createGroup(flagSet, "configs", "Configurations", flagSet.StringVar(&cfgFile, "config", "", "path to the nuclei configuration file"), + flagSet.BoolVarP(&options.FollowRedirects, "follow-redirects", "fr", false, "enable following redirects for http templates"), + flagSet.IntVarP(&options.MaxRedirects, "max-redirects", "mr", 10, "max number of redirects to follow for http templates"), flagSet.StringVarP(&options.ReportingConfig, "report-config", "rc", "", "nuclei reporting module configuration file"), // TODO merge into the config file or rename to issue-tracking flagSet.StringSliceVarP(&options.CustomHeaders, "header", "H", []string{}, "custom headers in header:value format"), flagSet.RuntimeMapVarP(&options.Vars, "var", "V", []string{}, "custom vars in var=value format"), diff --git a/v2/pkg/protocols/http/httpclientpool/clientpool.go b/v2/pkg/protocols/http/httpclientpool/clientpool.go index f1948300..f8439dc6 100644 --- a/v2/pkg/protocols/http/httpclientpool/clientpool.go +++ b/v2/pkg/protocols/http/httpclientpool/clientpool.go @@ -30,10 +30,11 @@ var ( // Dialer is a copy of the fastdialer from protocolstate Dialer *fastdialer.Dialer - rawHttpClient *rawhttp.Client - poolMutex *sync.RWMutex - normalClient *retryablehttp.Client - clientPool map[string]*retryablehttp.Client + rawHttpClient *rawhttp.Client + forceMaxRedirects int + poolMutex *sync.RWMutex + normalClient *retryablehttp.Client + clientPool map[string]*retryablehttp.Client ) // Init initializes the clientpool implementation @@ -42,6 +43,9 @@ func Init(options *types.Options) error { if normalClient != nil { return nil } + if options.FollowRedirects { + forceMaxRedirects = options.MaxRedirects + } poolMutex = &sync.RWMutex{} clientPool = make(map[string]*retryablehttp.Client) @@ -155,6 +159,10 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl followRedirects := configuration.FollowRedirects maxRedirects := configuration.MaxRedirects + if forceMaxRedirects > 0 { + followRedirects = true + maxRedirects = forceMaxRedirects + } // override connection's settings if required if configuration.Connection != nil { disableKeepAlives = configuration.Connection.DisableKeepAlive diff --git a/v2/pkg/types/types.go b/v2/pkg/types/types.go index f461518f..c4252bbc 100644 --- a/v2/pkg/types/types.go +++ b/v2/pkg/types/types.go @@ -119,6 +119,10 @@ type Options struct { // InteractionsCoolDownPeriod is additional seconds to wait for interactions after closing // of the poller. InteractionsCoolDownPeriod int + // MaxRedirects is the maximum numbers of redirects to be followed. + MaxRedirects int + // FollowRedirects enables following redirects for http request module + FollowRedirects bool // OfflineHTTP is a flag that specific offline processing of http response // using same matchers/extractors from http protocol without the need // to send a new request, reading responses from a file.