mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 23:25:27 +00:00
* 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>
202 lines
6.6 KiB
Go
202 lines
6.6 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
_ "net/http/pprof"
|
|
"strings"
|
|
|
|
"github.com/logrusorgru/aurora"
|
|
"github.com/projectdiscovery/gologger"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/frequency"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/stats"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider/http"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/projectfile"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/projectdiscovery/ratelimit"
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/core"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/loader/parser"
|
|
parsers "github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/progress"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/globalmatchers"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/hosterrorscache"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/excludematchers"
|
|
browserEngine "github.com/projectdiscovery/nuclei/v3/pkg/protocols/headless/engine"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
|
)
|
|
|
|
type nucleiExecutor struct {
|
|
engine *core.Engine
|
|
store *loader.Store
|
|
options *NucleiExecutorOptions
|
|
executorOpts *protocols.ExecutorOptions
|
|
}
|
|
|
|
type NucleiExecutorOptions struct {
|
|
Options *types.Options
|
|
Output output.Writer
|
|
Progress progress.Progress
|
|
Catalog catalog.Catalog
|
|
IssuesClient reporting.Client
|
|
RateLimiter *ratelimit.Limiter
|
|
Interactsh *interactsh.Client
|
|
ProjectFile *projectfile.ProjectFile
|
|
Browser *browserEngine.Browser
|
|
FuzzStatsDB *stats.Tracker
|
|
Colorizer aurora.Aurora
|
|
Parser parser.Parser
|
|
TemporaryDirectory string
|
|
Logger *gologger.Logger
|
|
}
|
|
|
|
func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) {
|
|
fuzzFreqCache := frequency.New(frequency.DefaultMaxTrackCount, opts.Options.FuzzParamFrequency)
|
|
resumeCfg := types.NewResumeCfg()
|
|
|
|
// Create the executor options which will be used throughout the execution
|
|
// stage by the nuclei engine modules.
|
|
executorOpts := &protocols.ExecutorOptions{
|
|
Output: opts.Output,
|
|
Options: opts.Options,
|
|
Progress: opts.Progress,
|
|
Catalog: opts.Catalog,
|
|
IssuesClient: opts.IssuesClient,
|
|
RateLimiter: opts.RateLimiter,
|
|
Interactsh: opts.Interactsh,
|
|
ProjectFile: opts.ProjectFile,
|
|
Browser: opts.Browser,
|
|
Colorizer: opts.Colorizer,
|
|
ResumeCfg: resumeCfg,
|
|
ExcludeMatchers: excludematchers.New(opts.Options.ExcludeMatchers),
|
|
InputHelper: input.NewHelper(),
|
|
TemporaryDirectory: opts.TemporaryDirectory,
|
|
Parser: opts.Parser,
|
|
FuzzParamsFrequency: fuzzFreqCache,
|
|
GlobalMatchers: globalmatchers.New(),
|
|
FuzzStatsDB: opts.FuzzStatsDB,
|
|
Logger: opts.Logger,
|
|
}
|
|
|
|
if opts.Options.ShouldUseHostError() {
|
|
maxHostError := opts.Options.MaxHostError
|
|
if maxHostError == 30 {
|
|
maxHostError = 100 // auto adjust for fuzzings
|
|
}
|
|
if opts.Options.TemplateThreads > maxHostError {
|
|
opts.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads)
|
|
|
|
maxHostError = opts.Options.TemplateThreads
|
|
}
|
|
|
|
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, opts.Options.TrackError)
|
|
cache.SetVerbose(opts.Options.Verbose)
|
|
|
|
executorOpts.HostErrorsCache = cache
|
|
}
|
|
|
|
executorEngine := core.New(opts.Options)
|
|
executorEngine.SetExecuterOptions(executorOpts)
|
|
|
|
workflowLoader, err := parsers.NewLoader(executorOpts)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Could not create loader options.")
|
|
}
|
|
executorOpts.WorkflowLoader = workflowLoader
|
|
|
|
// If using input-file flags, only load http fuzzing based templates.
|
|
loaderConfig := loader.NewConfig(opts.Options, opts.Catalog, executorOpts)
|
|
if !strings.EqualFold(opts.Options.InputFileMode, "list") || opts.Options.DAST || opts.Options.DASTServer {
|
|
// if input type is not list (implicitly enable fuzzing)
|
|
opts.Options.DAST = true
|
|
}
|
|
store, err := loader.New(loaderConfig)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Could not create loader options.")
|
|
}
|
|
store.Load()
|
|
|
|
return &nucleiExecutor{
|
|
engine: executorEngine,
|
|
store: store,
|
|
options: opts,
|
|
executorOpts: executorOpts,
|
|
}, nil
|
|
}
|
|
|
|
// proxifyRequest is a request for proxify
|
|
type proxifyRequest struct {
|
|
URL string `json:"url"`
|
|
Request struct {
|
|
Header map[string]string `json:"header"`
|
|
Body string `json:"body"`
|
|
Raw string `json:"raw"`
|
|
} `json:"request"`
|
|
}
|
|
|
|
func (n *nucleiExecutor) ExecuteScan(target PostRequestsHandlerRequest) error {
|
|
finalTemplates := []*templates.Template{}
|
|
finalTemplates = append(finalTemplates, n.store.Templates()...)
|
|
finalTemplates = append(finalTemplates, n.store.Workflows()...)
|
|
|
|
if len(finalTemplates) == 0 {
|
|
return errors.New("no templates provided for scan")
|
|
}
|
|
|
|
payload := proxifyRequest{
|
|
URL: target.URL,
|
|
Request: struct {
|
|
Header map[string]string `json:"header"`
|
|
Body string `json:"body"`
|
|
Raw string `json:"raw"`
|
|
}{
|
|
Raw: target.RawHTTP,
|
|
},
|
|
}
|
|
|
|
marshalledYaml, err := yaml.Marshal(payload)
|
|
if err != nil {
|
|
return fmt.Errorf("error marshalling yaml: %s", err)
|
|
}
|
|
|
|
inputProvider, err := http.NewHttpInputProvider(&http.HttpMultiFormatOptions{
|
|
InputContents: string(marshalledYaml),
|
|
InputMode: "yaml",
|
|
Options: formats.InputFormatOptions{
|
|
Variables: make(map[string]interface{}),
|
|
},
|
|
})
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not create input provider")
|
|
}
|
|
|
|
// We don't care about the result as its a boolean
|
|
// stating whether we got matches or not
|
|
_ = n.engine.ExecuteScanWithOpts(context.Background(), finalTemplates, inputProvider, true)
|
|
return nil
|
|
}
|
|
|
|
func (n *nucleiExecutor) Close() {
|
|
if n.executorOpts.FuzzStatsDB != nil {
|
|
n.executorOpts.FuzzStatsDB.Close()
|
|
}
|
|
if n.options.Interactsh != nil {
|
|
_ = n.options.Interactsh.Close()
|
|
}
|
|
if n.executorOpts.InputHelper != nil {
|
|
_ = n.executorOpts.InputHelper.Close()
|
|
}
|
|
|
|
}
|