Add support for CLI payload variables

dev
mzack 2021-10-07 12:36:27 +02:00
parent 514d6f94ec
commit 12b6b2ca89
8 changed files with 114 additions and 11 deletions

View File

@ -31,11 +31,11 @@ require (
github.com/pkg/errors v0.9.1
github.com/projectdiscovery/clistats v0.0.8
github.com/projectdiscovery/fastdialer v0.0.13-0.20210917073912-cad93d88e69e
github.com/projectdiscovery/goflags v0.0.7
github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5
github.com/projectdiscovery/goflags v0.0.8-0.20211007103353-9b9229e8a240
github.com/projectdiscovery/gologger v1.1.4
github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa
github.com/projectdiscovery/interactsh v0.0.4
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20210914222811-0a072d262f77
github.com/projectdiscovery/rawhttp v0.0.7
github.com/projectdiscovery/retryabledns v1.0.13-0.20210916165024-76c5b76fd59a
github.com/projectdiscovery/retryablehttp-go v1.0.2
@ -102,6 +102,7 @@ require (
github.com/projectdiscovery/iputil v0.0.0-20210804143329-3a30fcde43f3 // indirect
github.com/projectdiscovery/mapcidr v0.0.8 // indirect
github.com/projectdiscovery/networkpolicy v0.0.1 // indirect
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.7 // indirect
github.com/tklauser/numcpus v0.2.3 // indirect

View File

@ -341,8 +341,14 @@ github.com/projectdiscovery/cryptoutil v0.0.0-20210805184155-b5d2512f9345/go.mod
github.com/projectdiscovery/fastdialer v0.0.12/go.mod h1:RkRbxqDCcCFhfNUbkzBIz/ieD4uda2JuUA4WJ+RLee0=
github.com/projectdiscovery/fastdialer v0.0.13-0.20210917073912-cad93d88e69e h1:xMAFYJgRxopAwKrj7HDwMBKJGCGDbHqopS8f959xges=
github.com/projectdiscovery/fastdialer v0.0.13-0.20210917073912-cad93d88e69e/go.mod h1:O1l6+vAQy1QRo9FqyuyJ57W3CwpIXXg7oGo14Le6ZYQ=
github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5 h1:2dbm7UhrAKnccZttr78CAmG768sSCd+MBn4ayLVDeqA=
github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5/go.mod h1:U+QCpQnX8o2N2w0VUGyAzjM3yBAe4BKedVElxiImsx0=
github.com/projectdiscovery/goflags v0.0.7-0.20211007101748-dd9c32bab303 h1:5ownIWK6jZYdg/pM+H5wfC4zF0rOvDeHtejbpScZt8I=
github.com/projectdiscovery/goflags v0.0.7-0.20211007101748-dd9c32bab303/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
github.com/projectdiscovery/goflags v0.0.7 h1:aykmRkrOgDyRwcvGrK3qp+9aqcjGfAMs/+LtRmtyxwk=
github.com/projectdiscovery/goflags v0.0.7/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
github.com/projectdiscovery/goflags v0.0.8-0.20211007103353-9b9229e8a240 h1:b7zDUSsgN5f4/IlhKF6RVGsp/NkHIuty0o1YjzAMKUs=
github.com/projectdiscovery/goflags v0.0.8-0.20211007103353-9b9229e8a240/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
github.com/projectdiscovery/gologger v1.0.1/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE=
github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI=
github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY=
@ -365,8 +371,8 @@ github.com/projectdiscovery/mapcidr v0.0.8 h1:16U05F2x3o/jSTsxSCY2hCuCs9xOSwVxjo
github.com/projectdiscovery/mapcidr v0.0.8/go.mod h1:7CzdUdjuLVI0s33dQ33lWgjg3vPuLFw2rQzZ0RxkT00=
github.com/projectdiscovery/networkpolicy v0.0.1 h1:RGRuPlxE8WLFF9tdKSjTsYiTIKHNHW20Kl0nGGiRb1I=
github.com/projectdiscovery/networkpolicy v0.0.1/go.mod h1:asvdg5wMy3LPVMGALatebKeOYH5n5fV5RCTv6DbxpIs=
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20210914222811-0a072d262f77 h1:SNtAiRRrJtDJJDroaa/bFXt/Tix2LA6+rHRib0ORlJQ=
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20210914222811-0a072d262f77/go.mod h1:pxWVDgq88t9dWv4+J2AIaWgY+EqOE1AyfHS0Tn23w4M=
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df h1:CvTNAUD5JbLMqpMFoGNgfk2gOcN0NC57ICu0+oK84vs=
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df/go.mod h1:pxWVDgq88t9dWv4+J2AIaWgY+EqOE1AyfHS0Tn23w4M=
github.com/projectdiscovery/nuclei/v2 v2.5.1/go.mod h1:sU2qcY0MQFS0CqP1BgkR8ZnUyFhqK0BdnY6bvTKNjXY=
github.com/projectdiscovery/rawhttp v0.0.7 h1:5m4peVgjbl7gqDcRYMTVEuX+Xs/nh76ohTkkvufucLg=
github.com/projectdiscovery/rawhttp v0.0.7/go.mod h1:PQERZAhAv7yxI/hR6hdDPgK1WTU56l204BweXrBec+0=

View File

@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"github.com/projectdiscovery/fileutil"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/formatter"
"github.com/projectdiscovery/gologger/levels"
@ -61,6 +62,14 @@ func ParseOptions(options *types.Options) {
// Load the resolvers if user asked for them
loadResolvers(options)
// removes all cli variables containing payloads and add them to the internal struct
for key, value := range options.Vars.AsMap() {
if fileutil.FileExists(value.(string)) {
options.Vars.Del(key)
options.AddVarPayload(key, value)
}
}
err := protocolinit.Init(options)
if err != nil {
gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err)

View File

@ -30,3 +30,27 @@ func ContainsUnresolvedVariables(data string) error {
errorMessage := errorString.String()
return errors.New(errorMessage)
}
func ContainsVariablesWithNames(data string, names map[string]interface{}) error {
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
if len(matches) == 0 {
return nil
}
errorString := &strings.Builder{}
errorString.WriteString("unresolved variables with values found: ")
for i, match := range matches {
if len(match) < 2 {
continue
}
matchName := match[1]
if _, ok := names[matchName]; !ok {
errorString.WriteString(matchName)
if i != len(matches)-1 {
errorString.WriteString(",")
}
}
}
errorMessage := errorString.String()
return errors.New(errorMessage)
}

View File

@ -1,12 +1,15 @@
package http
import (
"fmt"
"strings"
"github.com/pkg/errors"
"github.com/projectdiscovery/fileutil"
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
"github.com/projectdiscovery/rawhttp"
@ -225,6 +228,36 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
r.CompiledOperators = compiled
}
// Resolve payload paths from vars if they exists
for name, payload := range r.options.Options.VarsPayload() {
payloadStr, ok := payload.(string)
// check if inputs contains the payload
var hasPayloadName bool
// search for markers in all request parts
var inputs []string
inputs = append(inputs, r.Method, r.Body)
inputs = append(inputs, r.Raw...)
for k, v := range r.customHeaders {
inputs = append(inputs, fmt.Sprintf("%s: %s", k, v))
}
for k, v := range r.Headers {
inputs = append(inputs, fmt.Sprintf("%s: %s", k, v))
}
for _, input := range inputs {
if expressions.ContainsVariablesWithNames(input, map[string]interface{}{name: payload}) == nil {
hasPayloadName = true
break
}
}
if ok && hasPayloadName && fileutil.FileExists(payloadStr) {
if r.Payloads == nil {
r.Payloads = make(map[string]interface{})
}
r.Payloads[name] = payloadStr
}
}
if len(r.Payloads) > 0 {
attackType := r.AttackType
if attackType == "" {

View File

@ -19,7 +19,6 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/tostring"
@ -288,12 +287,6 @@ func (r *Request) executeRequest(reqURL string, request *generatedRequest, previ
}
dumpedRequestString := string(dumpedRequest)
// Check if are there any unresolved variables. If yes, skip unless overriden by user.
if varErr := expressions.ContainsUnresolvedVariables(dumpedRequestString); varErr != nil && !r.SkipVariablesCheck {
gologger.Warning().Msgf("[%s] Could not make http request for %s: %v\n", r.options.TemplateID, reqURL, varErr)
return errStopExecution
}
if r.options.Options.Debug || r.options.Options.DebugRequests {
gologger.Info().Msgf("[%s] Dumped HTTP request for %s\n\n", r.options.TemplateID, reqURL)
gologger.Print().Msgf("%s", dumpedRequestString)

View File

@ -7,6 +7,7 @@ import (
"github.com/pkg/errors"
"github.com/projectdiscovery/fastdialer/fastdialer"
"github.com/projectdiscovery/fileutil"
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions"
@ -150,6 +151,28 @@ func (r *Request) Compile(options *protocols.ExecuterOptions) error {
}
}
// Resolve payload paths from vars if they exists
for name, payload := range r.options.Options.VarsPayload() {
payloadStr, ok := payload.(string)
// check if inputs contains the payload
var hasPayloadName bool
for _, input := range r.Inputs {
if input.Type != "" {
continue
}
if expressions.ContainsVariablesWithNames(input.Data, map[string]interface{}{name: payload}) == nil {
hasPayloadName = true
break
}
}
if ok && hasPayloadName && fileutil.FileExists(payloadStr) {
if r.Payloads == nil {
r.Payloads = make(map[string]interface{})
}
r.Payloads[name] = payloadStr
}
}
if len(r.Payloads) > 0 {
attackType := r.AttackType
if attackType == "" {

View File

@ -23,6 +23,8 @@ type Options struct {
CustomHeaders goflags.StringSlice
// Vars is the list of custom global vars
Vars goflags.RuntimeMap
// vars to use as iterative payload
varsPayload map[string]interface{}
// Severities filters templates based on their severity and only run the matching ones.
Severities severity.Severities
// Author filters templates based on their author and only run the matching ones.
@ -159,3 +161,15 @@ type Options struct {
// EnvironmentVariables enables support for environment variables
EnvironmentVariables bool
}
func (options *Options) AddVarPayload(key string, value interface{}) {
if options.varsPayload == nil {
options.varsPayload = make(map[string]interface{})
}
options.varsPayload[key] = value
}
func (options *Options) VarsPayload() map[string]interface{} {
return options.varsPayload
}