Skip to content
207 changes: 111 additions & 96 deletions pkg/fuzz/analyzers/analyzers.go
Original file line number Diff line number Diff line change
@@ -1,96 +1,111 @@
package analyzers

import (
"math/rand"
"strconv"
"strings"
"time"

"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
"github.com/projectdiscovery/retryablehttp-go"
)

// Analyzer is an interface for all the analyzers
// that can be used for the fuzzer
type Analyzer interface {
// Name returns the name of the analyzer
Name() string
// ApplyTransformation applies the transformation to the initial payload.
ApplyInitialTransformation(data string, params map[string]interface{}) string
// Analyze is the main function for the analyzer
Analyze(options *Options) (bool, string, error)
}

// AnalyzerTemplate is the template for the analyzer
type AnalyzerTemplate struct {
// description: |
// Name is the name of the analyzer to use
// values:
// - time_delay
Name string `json:"name" yaml:"name"`
// description: |
// Parameters is the parameters for the analyzer
//
// Parameters are different for each analyzer. For example, you can customize
// time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
// to the docs for each analyzer to get an idea about parameters.
Parameters map[string]interface{} `json:"parameters" yaml:"parameters"`
}

var (
analyzers map[string]Analyzer
)

// RegisterAnalyzer registers a new analyzer
func RegisterAnalyzer(name string, analyzer Analyzer) {
analyzers[name] = analyzer
}

// GetAnalyzer returns the analyzer for a given name
func GetAnalyzer(name string) Analyzer {
return analyzers[name]
}

func init() {
analyzers = make(map[string]Analyzer)
}

// Options contains the options for the analyzer
type Options struct {
FuzzGenerated fuzz.GeneratedRequest
HttpClient *retryablehttp.Client
ResponseTimeDelay time.Duration
AnalyzerParameters map[string]interface{}
}

var (
random = rand.New(rand.NewSource(time.Now().UnixNano()))
)

// ApplyPayloadTransformations applies the payload transformations to the payload
// It supports the below payloads -
// - [RANDNUM] => random number between 1000 and 9999
// - [RANDSTR] => random string of 4 characters
func ApplyPayloadTransformations(value string) string {
randomInt := GetRandomInteger()
randomStr := randStringBytesMask(4)

value = strings.ReplaceAll(value, "[RANDNUM]", strconv.Itoa(randomInt))
value = strings.ReplaceAll(value, "[RANDSTR]", randomStr)
return value
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func randStringBytesMask(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[random.Intn(len(letterBytes))]
}
return string(b)
}

// GetRandomInteger returns a random integer between 1000 and 9999
func GetRandomInteger() int {
return random.Intn(9000) + 1000
}
package analyzers

import (
"math/rand"
"strconv"
"strings"
"sync"
"time"

"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
"github.com/projectdiscovery/retryablehttp-go"
)

// Analyzer is an interface for all the analyzers
// that can be used for the fuzzer
type Analyzer interface {
// Name returns the name of the analyzer
Name() string
// ApplyTransformation applies the transformation to the initial payload.
ApplyInitialTransformation(data string, params map[string]interface{}) string
// Analyze is the main function for the analyzer
Analyze(options *Options) (bool, string, error)
}

// AnalyzerTemplate is the template for the analyzer
type AnalyzerTemplate struct {
// description: |
// Name is the name of the analyzer to use
// values:
// - time_delay
// - xss_context
Name string `json:"name" yaml:"name"`
// description: |
// Parameters is the parameters for the analyzer
//
// Parameters are different for each analyzer. For example, you can customize
// time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
// to the docs for each analyzer to get an idea about parameters.
Parameters map[string]interface{} `json:"parameters" yaml:"parameters"`
}

var (
analyzers map[string]Analyzer
)

// RegisterAnalyzer registers a new analyzer
func RegisterAnalyzer(name string, analyzer Analyzer) {
analyzers[name] = analyzer
}

// GetAnalyzer returns the analyzer for a given name
func GetAnalyzer(name string) Analyzer {
return analyzers[name]
}

func init() {
analyzers = make(map[string]Analyzer)
}

// Options contains the options for the analyzer
type Options struct {
FuzzGenerated fuzz.GeneratedRequest
HttpClient *retryablehttp.Client
ResponseTimeDelay time.Duration
AnalyzerParameters map[string]interface{}

// ResponseBody is the body of the HTTP response
ResponseBody string
// ResponseHeaders is the headers of the HTTP response
ResponseHeaders map[string][]string
// ResponseStatusCode is the status code of the HTTP response
ResponseStatusCode int
}

var (
random = rand.New(rand.NewSource(time.Now().UnixNano()))
randomMu sync.Mutex
)

// ApplyPayloadTransformations applies the payload transformations to the payload
// It supports the below payloads -
// - [RANDNUM] => random number between 1000 and 9999
// - [RANDSTR] => random string of 4 characters
func ApplyPayloadTransformations(value string) string {
randomInt := GetRandomInteger()
randomStr := RandStringBytesMask(4)

value = strings.ReplaceAll(value, "[RANDNUM]", strconv.Itoa(randomInt))
value = strings.ReplaceAll(value, "[RANDSTR]", randomStr)
return value
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// RandStringBytesMask generates a random string of n characters
func RandStringBytesMask(n int) string {
randomMu.Lock()
defer randomMu.Unlock()
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[random.Intn(len(letterBytes))]
}
return string(b)
}

// GetRandomInteger returns a random integer between 1000 and 9999
func GetRandomInteger() int {
randomMu.Lock()
defer randomMu.Unlock()
return random.Intn(9000) + 1000
}
Loading