Adding variables support for headless templates (#2064)

dev
Mzack9999 2022-05-27 18:01:56 +02:00 committed by GitHub
parent 05fdff8170
commit 02eaf91e6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 38 additions and 26 deletions

View File

@ -47,15 +47,14 @@ func MergeMapsMany(maps ...interface{}) map[string][]string {
} }
// MergeMaps merges two maps into a new map // MergeMaps merges two maps into a new map
func MergeMaps(m1, m2 map[string]interface{}) map[string]interface{} { func MergeMaps(maps ...map[string]interface{}) map[string]interface{} {
m := make(map[string]interface{}, len(m1)+len(m2)) merged := make(map[string]interface{})
for k, v := range m1 { for _, m := range maps {
m[k] = v for k, v := range m {
merged[k] = v
} }
for k, v := range m2 {
m[k] = v
} }
return m return merged
} }
// ExpandMapValues converts values from flat string to string slice // ExpandMapValues converts values from flat string to string slice

View File

@ -7,10 +7,10 @@ import (
) )
func TestMergeMapsMany(t *testing.T) { func TestMergeMapsMany(t *testing.T) {
got := MergeMapsMany(map[string]interface{}{"a": []string{"1", "2"}, "c": "5"}, map[string][]string{"b": []string{"3", "4"}}) got := MergeMapsMany(map[string]interface{}{"a": []string{"1", "2"}, "c": "5"}, map[string][]string{"b": {"3", "4"}})
require.Equal(t, map[string][]string{ require.Equal(t, map[string][]string{
"a": []string{"1", "2"}, "a": {"1", "2"},
"b": []string{"3", "4"}, "b": {"3", "4"},
"c": []string{"5"}, "c": {"5"},
}, got, "could not get correct merged map") }, got, "could not get correct merged map")
} }

View File

@ -245,8 +245,8 @@ func classToInt(class string) uint16 {
return uint16(result) return uint16(result)
} }
// GenerateDNSVariables from a dns name // GenerateVariables from a dns name
func GenerateDNSVariables(domain string) map[string]interface{} { func GenerateVariables(domain string) map[string]interface{} {
parsed, err := publicsuffix.Parse(strings.TrimSuffix(domain, ".")) parsed, err := publicsuffix.Parse(strings.TrimSuffix(domain, "."))
if err != nil { if err != nil {
return map[string]interface{}{"FQDN": domain} return map[string]interface{}{"FQDN": domain}

View File

@ -11,7 +11,7 @@ import (
) )
func TestGenerateDNSVariables(t *testing.T) { func TestGenerateDNSVariables(t *testing.T) {
vars := GenerateDNSVariables("www.projectdiscovery.io") vars := GenerateVariables("www.projectdiscovery.io")
require.Equal(t, map[string]interface{}{ require.Equal(t, map[string]interface{}{
"FQDN": "www.projectdiscovery.io", "FQDN": "www.projectdiscovery.io",
"RDN": "projectdiscovery.io", "RDN": "projectdiscovery.io",

View File

@ -43,7 +43,7 @@ func (request *Request) ExecuteWithResults(input string, metadata /*TODO review
if err != nil { if err != nil {
return errors.Wrap(err, "could not build request") return errors.Wrap(err, "could not build request")
} }
vars := GenerateDNSVariables(domain) vars := GenerateVariables(domain)
variablesMap := request.options.Variables.Evaluate(vars) variablesMap := request.options.Variables.Evaluate(vars)
vars = generators.MergeMaps(variablesMap, vars) vars = generators.MergeMaps(variablesMap, vars)

View File

@ -14,6 +14,7 @@ import (
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/eventcreator" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/eventcreator"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/responsehighlighter" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/responsehighlighter"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh" "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh"
httpProtocol "github.com/projectdiscovery/nuclei/v2/pkg/protocols/http"
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types" templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
) )
@ -31,9 +32,11 @@ func (request *Request) ExecuteWithResults(inputURL string, metadata, previous o
if request.options.Browser.UserAgent() == "" { if request.options.Browser.UserAgent() == "" {
request.options.Browser.SetUserAgent(request.compiledUserAgent) request.options.Browser.SetUserAgent(request.compiledUserAgent)
} }
payloads := generators.BuildPayloadFromOptions(request.options.Options)
variablesMap := request.options.Variables.Evaluate(generators.MergeMaps(metadata, payloads)) vars := GenerateVariables(inputURL)
payloads := generators.BuildPayloadFromOptions(request.options.Options)
values := generators.MergeMaps(vars, metadata, payloads)
variablesMap := request.options.Variables.Evaluate(values)
payloads = generators.MergeMaps(variablesMap, payloads) payloads = generators.MergeMaps(variablesMap, payloads)
if request.generator != nil { if request.generator != nil {
@ -141,3 +144,13 @@ func dumpResponse(event *output.InternalWrappedEvent, requestOptions *protocols.
gologger.Debug().Msgf("[%s] Dumped Headless response for %s\n\n%s", requestOptions.TemplateID, input, highlightedResponse) gologger.Debug().Msgf("[%s] Dumped Headless response for %s\n\n%s", requestOptions.TemplateID, input, highlightedResponse)
} }
} }
// GenerateVariables will create default variables
func GenerateVariables(URL string) map[string]interface{} {
parsed, err := url.Parse(URL)
if err != nil {
return nil
}
return httpProtocol.GenerateVariables(parsed, false)
}

View File

@ -93,7 +93,7 @@ func (r *requestGenerator) Make(baseURL, data string, payloads, dynamicValues ma
} }
values := generators.MergeMaps( values := generators.MergeMaps(
generators.MergeMaps(dynamicValues, generateVariables(parsed, trailingSlash)), generators.MergeMaps(dynamicValues, GenerateVariables(parsed, trailingSlash)),
generators.BuildPayloadFromOptions(r.request.options.Options), generators.BuildPayloadFromOptions(r.request.options.Options),
) )
@ -156,7 +156,7 @@ func (r *requestGenerator) makeSelfContainedRequest(data string, payloads, dynam
return nil, fmt.Errorf("could not parse request URL: %w", err) return nil, fmt.Errorf("could not parse request URL: %w", err)
} }
values = generators.MergeMaps( values = generators.MergeMaps(
generators.MergeMaps(dynamicValues, generateVariables(parsed, false)), generators.MergeMaps(dynamicValues, GenerateVariables(parsed, false)),
values, values,
) )
@ -377,8 +377,8 @@ func setHeader(req *http.Request, name, value string) {
} }
} }
// generateVariables will create default variables after parsing a url // GenerateVariables will create default variables after parsing a url
func generateVariables(parsed *url.URL, trailingSlash bool) map[string]interface{} { func GenerateVariables(parsed *url.URL, trailingSlash bool) map[string]interface{} {
domain := parsed.Host domain := parsed.Host
if strings.Contains(parsed.Host, ":") { if strings.Contains(parsed.Host, ":") {
domain = strings.Split(parsed.Host, ":")[0] domain = strings.Split(parsed.Host, ":")[0]
@ -416,5 +416,5 @@ func generateVariables(parsed *url.URL, trailingSlash bool) map[string]interface
"File": base, "File": base,
"Scheme": parsed.Scheme, "Scheme": parsed.Scheme,
} }
return generators.MergeMaps(httpVariables, dns.GenerateDNSVariables(domain)) return generators.MergeMaps(httpVariables, dns.GenerateVariables(domain))
} }

View File

@ -27,7 +27,7 @@ func TestBaseURLWithTemplatePrefs(t *testing.T) {
func TestVariables(t *testing.T) { func TestVariables(t *testing.T) {
baseURL := "http://localhost:9001/test/123" baseURL := "http://localhost:9001/test/123"
parsed, _ := url.Parse(baseURL) parsed, _ := url.Parse(baseURL)
values := generateVariables(parsed, true) values := GenerateVariables(parsed, true)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl") require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["RootURL"], "http://localhost:9001", "incorrect rootURL") require.Equal(t, values["RootURL"], "http://localhost:9001", "incorrect rootURL")
@ -40,7 +40,7 @@ func TestVariables(t *testing.T) {
baseURL = "https://example.com" baseURL = "https://example.com"
parsed, _ = url.Parse(baseURL) parsed, _ = url.Parse(baseURL)
values = generateVariables(parsed, false) values = GenerateVariables(parsed, false)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl") require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["Host"], "example.com", "incorrect domain name") require.Equal(t, values["Host"], "example.com", "incorrect domain name")
@ -52,7 +52,7 @@ func TestVariables(t *testing.T) {
baseURL = "ftp://foobar.com/" baseURL = "ftp://foobar.com/"
parsed, _ = url.Parse(baseURL) parsed, _ = url.Parse(baseURL)
values = generateVariables(parsed, true) values = GenerateVariables(parsed, true)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl") require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["Host"], "foobar.com", "incorrect domain name") require.Equal(t, values["Host"], "foobar.com", "incorrect domain name")