begin of work on fuzzing - only working for raw requests with payload (TODO code cleanup)

dev
Mzack9999 2020-05-04 23:24:59 +02:00
parent 443140a52f
commit 44821e6b77
12 changed files with 519 additions and 122 deletions

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.14
require ( require (
github.com/Knetic/govaluate v3.0.0+incompatible github.com/Knetic/govaluate v3.0.0+incompatible
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535
github.com/karrick/godirwalk v1.15.6
github.com/miekg/dns v1.1.29 github.com/miekg/dns v1.1.29
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/projectdiscovery/gologger v1.0.0 github.com/projectdiscovery/gologger v1.0.0

2
go.sum
View File

@ -4,6 +4,8 @@ github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8L
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/karrick/godirwalk v1.15.6 h1:Yf2mmR8TJy+8Fa0SuQVto5SYap6IF7lNVX4Jdl8G1qA=
github.com/karrick/godirwalk v1.15.6/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=

View File

@ -78,7 +78,7 @@ func (e *HTTPExecutor) ExecuteHTTP(URL string) error {
// Send the request to the target servers // Send the request to the target servers
mainLoop: mainLoop:
for _, req := range compiledRequest { for req := range compiledRequest {
resp, err := e.httpClient.Do(req) resp, err := e.httpClient.Do(req)
if err != nil { if err != nil {
if resp != nil { if resp != nil {

20
pkg/generators/attack.go Normal file
View File

@ -0,0 +1,20 @@
package generators
// Type is type of attack
type Type int
const (
// Sniper attack - each variable replaced with values at a time
Sniper Type = iota + 1
// PitchFork attack - Each variable replaced with positional value in multiple wordlists
PitchFork
// ClusterBomb attack - Generate all possible combinations of values
ClusterBomb
)
// AttackTypes is an table for conversion of attack type from string.
var AttackTypes = map[string]Type{
"sniper": Sniper,
"pitchfork": PitchFork,
"clusterbomb": ClusterBomb,
}

View File

@ -0,0 +1,50 @@
package generators
// ClusterbombGenerator Attack - Generate all possible combinations from an input map with all values listed
// as slices of the same size
func ClusterbombGenerator(payloads map[string][]string) (out chan map[string]interface{}) {
out = make(chan map[string]interface{})
// generator
go func() {
defer close(out)
var order []string
var parts [][]string
for name, wordlist := range payloads {
order = append(order, name)
parts = append(parts, wordlist)
}
var n = 1
for _, ar := range parts {
n *= len(ar)
}
var at = make([]int, len(parts))
loop:
for {
// increment position counters
for i := len(parts) - 1; i >= 0; i-- {
if at[i] > 0 && at[i] >= len(parts[i]) {
if i == 0 || (i == 1 && at[i-1] == len(parts[0])-1) {
break loop
}
at[i] = 0
at[i-1]++
}
}
// construct permutation
item := make(map[string]interface{})
for i, ar := range parts {
var p = at[i]
if p >= 0 && p < len(ar) {
item[order[i]] = ar[p]
}
}
out <- item
at[len(parts)-1]++
}
}()
return out
}

103
pkg/generators/dsl.go Normal file
View File

@ -0,0 +1,103 @@
package generators
import (
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"html"
"net/url"
"regexp"
"strings"
"github.com/Knetic/govaluate"
)
// HelperFunctions contains the dsl functions
func HelperFunctions() (functions map[string]govaluate.ExpressionFunction) {
functions = make(map[string]govaluate.ExpressionFunction)
// strings
functions["len"] = func(args ...interface{}) (interface{}, error) {
length := len(args[0].(string))
return (float64)(length), nil
}
functions["toupper"] = func(args ...interface{}) (interface{}, error) {
return strings.ToUpper(args[0].(string)), nil
}
functions["tolower"] = func(args ...interface{}) (interface{}, error) {
return strings.ToLower(args[0].(string)), nil
}
functions["replace"] = func(args ...interface{}) (interface{}, error) {
return strings.Replace(args[0].(string), args[1].(string), args[2].(string), -1), nil
}
functions["trim"] = func(args ...interface{}) (interface{}, error) {
return strings.Trim(args[0].(string), args[2].(string)), nil
}
functions["trimleft"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimLeft(args[0].(string), args[1].(string)), nil
}
functions["trimright"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimRight(args[0].(string), args[1].(string)), nil
}
functions["trimspace"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimSpace(args[0].(string)), nil
}
functions["trimprefix"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimPrefix(args[0].(string), args[1].(string)), nil
}
functions["trimsuffix"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimSuffix(args[0].(string), args[1].(string)), nil
}
functions["reverse"] = func(args ...interface{}) (interface{}, error) {
return reverseString(args[0].(string)), nil
}
// encoding
functions["base64"] = func(args ...interface{}) (interface{}, error) {
sEnc := base64.StdEncoding.EncodeToString([]byte(args[0].(string)))
return sEnc, nil
}
functions["base64_decode"] = func(args ...interface{}) (interface{}, error) {
sEnc := base64.StdEncoding.EncodeToString([]byte(args[0].(string)))
return sEnc, nil
}
functions["url_encode"] = func(args ...interface{}) (interface{}, error) {
return url.PathEscape(args[0].(string)), nil
}
functions["url_decode"] = func(args ...interface{}) (interface{}, error) {
return url.PathUnescape(args[0].(string))
}
functions["hex_encode"] = func(args ...interface{}) (interface{}, error) {
return hex.EncodeToString([]byte(args[0].(string))), nil
}
functions["hex_decode"] = func(args ...interface{}) (interface{}, error) {
hx, _ := hex.DecodeString(args[0].(string))
return string(hx), nil
}
functions["html_escape"] = func(args ...interface{}) (interface{}, error) {
return html.EscapeString(args[0].(string)), nil
}
functions["html_unescape"] = func(args ...interface{}) (interface{}, error) {
return html.UnescapeString(args[0].(string)), nil
}
// hashing
functions["md5"] = func(args ...interface{}) (interface{}, error) {
hash := md5.Sum([]byte(args[0].(string)))
return hex.EncodeToString(hash[:]), nil
}
functions["sha256"] = func(args ...interface{}) (interface{}, error) {
return sha256.Sum256([]byte(args[0].(string))), nil
}
// search
functions["contains"] = func(args ...interface{}) (interface{}, error) {
return strings.Contains(args[0].(string), args[1].(string)), nil
}
functions["regex"] = func(args ...interface{}) (interface{}, error) {
compiled, err := regexp.Compile(args[0].(string))
if err != nil {
return nil, err
}
return compiled.MatchString(args[1].(string)), nil
}
return
}

View File

@ -0,0 +1,38 @@
package generators
// PitchforkGenerator Attack - Generate positional combinations from an input map with all values listed
// as slices of the same size
func PitchforkGenerator(payloads map[string][]string) (out chan map[string]interface{}) {
out = make(chan map[string]interface{})
size := 0
// check if all wordlists have the same size
for _, wordlist := range payloads {
if size == 0 {
size = len(wordlist)
}
if len(wordlist) != size {
//set size = 0 and exit the cycle
size = 0
break
}
}
// generator
go func() {
defer close(out)
for i := 0; i < size; i++ {
element := make(map[string]interface{})
for name, wordlist := range payloads {
element[name] = wordlist[i]
}
out <- element
}
}()
return out
}

21
pkg/generators/sniper.go Normal file
View File

@ -0,0 +1,21 @@
package generators
// SniperGenerator Attack - Generate sequential combinations
func SniperGenerator(payloads map[string][]string) (out chan map[string]interface{}) {
out = make(chan map[string]interface{})
// generator
go func() {
defer close(out)
for name, wordlist := range payloads {
for _, value := range wordlist {
element := CopyMapWithDefaultValue(payloads, "")
element[name] = value
out <- element
}
}
}()
return out
}

108
pkg/generators/util.go Normal file
View File

@ -0,0 +1,108 @@
package generators
import (
"bufio"
"os"
"strings"
)
// LoadWordlists creating proper data structure
func LoadWordlists(payloads map[string]string) map[string][]string {
wordlists := make(map[string][]string)
// load all wordlists
for name, filepath := range payloads {
wordlists[name] = LoadFile(filepath)
}
return wordlists
}
// LoadFile into slice of strings
func LoadFile(filepath string) (lines []string) {
for line := range StreamFile(filepath) {
lines = append(lines, line)
}
return
}
// StreamFile content to a chan
func StreamFile(filepath string) (content chan string) {
content = make(chan string)
go func() {
defer close(content)
file, err := os.Open(filepath)
if err != nil {
return
}
defer file.Close()
// yql filter applied
scanner := bufio.NewScanner(file)
for scanner.Scan() {
content <- scanner.Text()
}
if err := scanner.Err(); err != nil {
return
}
}()
return
}
// MergeMaps into a new one
func MergeMaps(m1, m2 map[string]interface{}) (m map[string]interface{}) {
m = make(map[string]interface{})
for k, v := range m1 {
m[k] = v
}
for k, v := range m2 {
m[k] = v
}
return m
}
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
// CopyMap creates a new copy of an existing map
func CopyMap(originalMap map[string]interface{}) map[string]interface{} {
newMap := make(map[string]interface{})
for key, value := range originalMap {
newMap[key] = value
}
return newMap
}
// CopyMapWithDefaultValue creates a new copy of an existing map and set a default value
func CopyMapWithDefaultValue(originalMap map[string][]string, defaultValue interface{}) map[string]interface{} {
newMap := make(map[string]interface{})
for key := range originalMap {
newMap[key] = defaultValue
}
return newMap
}
// StringContainsAnyMapItem verifies is a string contains any value of a map
func StringContainsAnyMapItem(m map[string]interface{}, s string) bool {
for key := range m {
if strings.Contains(s, key) {
return true
}
}
return false
}
// TrimDelimiters removes trailing brackets
func TrimDelimiters(s string) string {
return strings.TrimSuffix(strings.TrimPrefix(s, "{{"), "}}")
}

View File

@ -1,15 +1,11 @@
package matchers package matchers
import ( import (
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt" "fmt"
"regexp" "regexp"
"strings"
"github.com/Knetic/govaluate" "github.com/Knetic/govaluate"
"github.com/projectdiscovery/nuclei/pkg/generators"
) )
// CompileMatchers performs the initial setup operation on a matcher // CompileMatchers performs the initial setup operation on a matcher
@ -34,7 +30,7 @@ func (m *Matcher) CompileMatchers() error {
// Compile the dsl expressions // Compile the dsl expressions
for _, dsl := range m.DSL { for _, dsl := range m.DSL {
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(dsl, helperFunctions()) compiled, err := govaluate.NewEvaluableExpressionWithFunctions(dsl, generators.HelperFunctions())
if err != nil { if err != nil {
return fmt.Errorf("could not compile dsl: %s", dsl) return fmt.Errorf("could not compile dsl: %s", dsl)
} }
@ -63,69 +59,3 @@ func (m *Matcher) CompileMatchers() error {
} }
return nil return nil
} }
func helperFunctions() (functions map[string]govaluate.ExpressionFunction) {
functions = make(map[string]govaluate.ExpressionFunction)
// strings
functions["len"] = func(args ...interface{}) (interface{}, error) {
length := len(args[0].(string))
return (float64)(length), nil
}
functions["toupper"] = func(args ...interface{}) (interface{}, error) {
return strings.ToUpper(args[0].(string)), nil
}
functions["tolower"] = func(args ...interface{}) (interface{}, error) {
return strings.ToLower(args[0].(string)), nil
}
functions["replace"] = func(args ...interface{}) (interface{}, error) {
return strings.Replace(args[0].(string), args[1].(string), args[2].(string), -1), nil
}
functions["trim"] = func(args ...interface{}) (interface{}, error) {
return strings.Trim(args[0].(string), args[2].(string)), nil
}
functions["trimleft"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimLeft(args[0].(string), args[1].(string)), nil
}
functions["trimright"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimRight(args[0].(string), args[1].(string)), nil
}
functions["trimspace"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimSpace(args[0].(string)), nil
}
functions["trimprefix"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimPrefix(args[0].(string), args[1].(string)), nil
}
functions["trimsuffix"] = func(args ...interface{}) (interface{}, error) {
return strings.TrimSuffix(args[0].(string), args[1].(string)), nil
}
// encoding
functions["base64"] = func(args ...interface{}) (interface{}, error) {
sEnc := base64.StdEncoding.EncodeToString([]byte(args[0].(string)))
return sEnc, nil
}
functions["base64_decode"] = func(args ...interface{}) (interface{}, error) {
sEnc := base64.StdEncoding.EncodeToString([]byte(args[0].(string)))
return sEnc, nil
}
// hashing
functions["md5"] = func(args ...interface{}) (interface{}, error) {
hash := md5.Sum([]byte(args[0].(string)))
return hex.EncodeToString(hash[:]), nil
}
functions["sha256"] = func(args ...interface{}) (interface{}, error) {
return sha256.Sum256([]byte(args[0].(string))), nil
}
// search
functions["contains"] = func(args ...interface{}) (interface{}, error) {
return strings.Contains(args[0].(string), args[1].(string)), nil
}
functions["regex"] = func(args ...interface{}) (interface{}, error) {
compiled, err := regexp.Compile(args[0].(string))
if err != nil {
return nil, err
}
return compiled.MatchString(args[1].(string)), nil
}
return
}

View File

@ -4,17 +4,28 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"net/url" "net/url"
"regexp"
"strings" "strings"
"github.com/Knetic/govaluate"
"github.com/projectdiscovery/nuclei/pkg/extractors" "github.com/projectdiscovery/nuclei/pkg/extractors"
"github.com/projectdiscovery/nuclei/pkg/generators"
"github.com/projectdiscovery/nuclei/pkg/matchers" "github.com/projectdiscovery/nuclei/pkg/matchers"
retryablehttp "github.com/projectdiscovery/retryablehttp-go" retryablehttp "github.com/projectdiscovery/retryablehttp-go"
) )
// HTTPRequest contains a request to be made from a template // HTTPRequest contains a request to be made from a template
type HTTPRequest struct { type HTTPRequest struct {
// AttackType is the attack type
// Sniper, PitchFork and ClusterBomb. Default is Sniper
AttackType string `yaml:"attack,omitempty"`
// attackType is internal attack type
attackType generators.Type
// Path contains the path/s for the request variables
Payloads map[string]string `yaml:"payloads,omitempty"`
// Method is the request method, whether GET, POST, PUT, etc // Method is the request method, whether GET, POST, PUT, etc
Method string `yaml:"method"` Method string `yaml:"method"`
// Path contains the path/s for the request // Path contains the path/s for the request
@ -52,8 +63,18 @@ func (r *HTTPRequest) SetMatchersCondition(condition matchers.ConditionType) {
r.matchersCondition = condition r.matchersCondition = condition
} }
// GetAttackType returns the attack
func (r *HTTPRequest) GetAttackType() generators.Type {
return r.attackType
}
// SetAttackType sets the attack
func (r *HTTPRequest) SetAttackType(attack generators.Type) {
r.attackType = attack
}
// MakeHTTPRequest creates a *http.Request from a request configuration // MakeHTTPRequest creates a *http.Request from a request configuration
func (r *HTTPRequest) MakeHTTPRequest(baseURL string) ([]*retryablehttp.Request, error) { func (r *HTTPRequest) MakeHTTPRequest(baseURL string) (chan *retryablehttp.Request, error) {
parsed, err := url.Parse(baseURL) parsed, err := url.Parse(baseURL)
if err != nil { if err != nil {
return nil, err return nil, err
@ -73,43 +94,100 @@ func (r *HTTPRequest) MakeHTTPRequest(baseURL string) ([]*retryablehttp.Request,
} }
// MakeHTTPRequestFromModel creates a *http.Request from a request template // MakeHTTPRequestFromModel creates a *http.Request from a request template
func (r *HTTPRequest) makeHTTPRequestFromModel(baseURL string, values map[string]interface{}) (requests []*retryablehttp.Request, err error) { func (r *HTTPRequest) makeHTTPRequestFromModel(baseURL string, values map[string]interface{}) (requests chan *retryablehttp.Request, err error) {
replacer := newReplacer(values) requests = make(chan *retryablehttp.Request)
// request generator
go func() {
defer close(requests)
for _, path := range r.Path { for _, path := range r.Path {
// process base request
replacer := newReplacer(values)
// Replace the dynamic variables in the URL if any // Replace the dynamic variables in the URL if any
URL := replacer.Replace(path) URL := replacer.Replace(path)
// Build a request on the specified URL // Build a request on the specified URL
req, err := http.NewRequest(r.Method, URL, nil) req, err := http.NewRequest(r.Method, URL, nil)
if err != nil { if err != nil {
return nil, err // find a way to pass the error
return
} }
request, err := r.fillRequest(req, values) request, err := r.fillRequest(req, values)
if err != nil { if err != nil {
return nil, err // find a way to pass the error
return
} }
requests = append(requests, request) requests <- request
} }
}()
return return
} }
// makeHTTPRequestFromRaw creates a *http.Request from a raw request // makeHTTPRequestFromRaw creates a *http.Request from a raw request
func (r *HTTPRequest) makeHTTPRequestFromRaw(baseURL string, values map[string]interface{}) (requests []*retryablehttp.Request, err error) { func (r *HTTPRequest) makeHTTPRequestFromRaw(baseURL string, values map[string]interface{}) (requests chan *retryablehttp.Request, err error) {
replacer := newReplacer(values) requests = make(chan *retryablehttp.Request)
// request generator
go func() {
defer close(requests)
for _, raw := range r.Raw { for _, raw := range r.Raw {
// Add trailing line // Add trailing line
raw += "\n" raw += "\n"
if len(r.Payloads) > 0 {
basePayloads := generators.LoadWordlists(r.Payloads)
generatorFunc := generators.SniperGenerator
switch r.attackType {
case generators.PitchFork:
generatorFunc = generators.PitchforkGenerator
case generators.ClusterBomb:
generatorFunc = generators.ClusterbombGenerator
}
for genValues := range generatorFunc(basePayloads) {
baseValues := generators.CopyMap(values)
finValues := generators.MergeMaps(baseValues, genValues)
replacer := newReplacer(finValues)
// Replace the dynamic variables in the URL if any // Replace the dynamic variables in the URL if any
raw = replacer.Replace(raw) raw := replacer.Replace(raw)
dynamicValues := make(map[string]interface{})
// find all potentials tokens between {{}}
var re = regexp.MustCompile(`(?m)\{\{.+}}`)
for _, match := range re.FindAllString(raw, -1) {
// check if the match contains a dynamic variable
if generators.StringContainsAnyMapItem(finValues, match) {
expr := generators.TrimDelimiters(match)
compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expr, generators.HelperFunctions())
if err != nil {
// Debug only - Remove
log.Fatal(err)
}
result, err := compiled.Evaluate(finValues)
if err != nil {
// Debug only - Remove
log.Fatal(err)
}
dynamicValues[expr] = result
}
}
// replace dynamic values
dynamicReplacer := newReplacer(dynamicValues)
raw = dynamicReplacer.Replace(raw)
// log.Println(raw)
// Build a parsed request from raw // Build a parsed request from raw
parsedReq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(raw))) parsedReq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(raw)))
if err != nil { if err != nil {
return nil, err return
} }
// requests generated from http.ReadRequest have incorrect RequestURI, so they // requests generated from http.ReadRequest have incorrect RequestURI, so they
@ -118,7 +196,7 @@ func (r *HTTPRequest) makeHTTPRequestFromRaw(baseURL string, values map[string]i
finalURL := fmt.Sprintf("%s%s", baseURL, parsedReq.URL) finalURL := fmt.Sprintf("%s%s", baseURL, parsedReq.URL)
req, err := http.NewRequest(r.Method, finalURL, parsedReq.Body) req, err := http.NewRequest(r.Method, finalURL, parsedReq.Body)
if err != nil { if err != nil {
return nil, err return
} }
// copy headers // copy headers
@ -126,11 +204,49 @@ func (r *HTTPRequest) makeHTTPRequestFromRaw(baseURL string, values map[string]i
request, err := r.fillRequest(req, values) request, err := r.fillRequest(req, values)
if err != nil { if err != nil {
return nil, err return
} }
requests = append(requests, request) requests <- request
} }
} else {
// otherwise continue with normal flow
// base request
replacer := newReplacer(values)
// Replace the dynamic variables in the request if any
raw = replacer.Replace(raw)
// Build a parsed request from raw
parsedReq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(raw)))
if err != nil {
// find a way to pass the error
return
}
// requests generated from http.ReadRequest have incorrect RequestURI, so they
// cannot be used to perform another request directly, we need to generate a new one
// with the new target url
finalURL := fmt.Sprintf("%s%s", baseURL, parsedReq.URL)
req, err := http.NewRequest(r.Method, finalURL, parsedReq.Body)
if err != nil {
// find a way to pass the error
return
}
// copy headers
req.Header = parsedReq.Header.Clone()
request, err := r.fillRequest(req, values)
if err != nil {
// find a way to pass the error
return
}
requests <- request
}
}
}()
return requests, nil return requests, nil
} }

View File

@ -3,6 +3,7 @@ package templates
import ( import (
"os" "os"
"github.com/projectdiscovery/nuclei/pkg/generators"
"github.com/projectdiscovery/nuclei/pkg/matchers" "github.com/projectdiscovery/nuclei/pkg/matchers"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -33,6 +34,13 @@ func ParseTemplate(file string) (*Template, error) {
request.SetMatchersCondition(condition) request.SetMatchersCondition(condition)
} }
attack, ok := generators.AttackTypes[request.AttackType]
if !ok {
request.SetAttackType(generators.Sniper)
} else {
request.SetAttackType(attack)
}
for _, matcher := range request.Matchers { for _, matcher := range request.Matchers {
if err = matcher.CompileMatchers(); err != nil { if err = matcher.CompileMatchers(); err != nil {
return nil, err return nil, err