nuclei/pkg/protocols/utils/variables_test.go

169 lines
6.0 KiB
Go
Raw Normal View History

package utils
import (
"context"
"reflect"
"testing"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
urlutil "github.com/projectdiscovery/utils/url"
"github.com/stretchr/testify/require"
)
func TestHTTPVariables(t *testing.T) {
baseURL := "http://localhost:9001/test/123"
parsed, _ := urlutil.Parse(baseURL)
Spelling (#4008) * spelling: addresses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: asynchronous Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: basic Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: brute force Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: constant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disables Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: engine Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: every time Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: execution Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: false positives Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: from Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: further Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: gitlab Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: highlight Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hygiene Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: ignore Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: input Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: item Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: itself Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: latestxxx Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: navigation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: negative Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: nonexistent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: override Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: overrides Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: payload Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: performed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: respective Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: retrieve Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: scanlist Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: severity Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: source Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: strategy Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: string Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: templates Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: terminal Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: timeout Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: trailing slash Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: trailing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: websocket Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --------- Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-08-01 14:33:43 -04:00
// trailing slash is only true when both target/inputURL and payload {{BaseURL}}/xyz both have slash
values := GenerateVariables(parsed, false, nil)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["RootURL"], "http://localhost:9001", "incorrect rootURL")
require.Equal(t, values["Host"], "localhost", "incorrect domain name")
require.Equal(t, values["Path"], "/test", "incorrect path")
require.Equal(t, values["File"], "123", "incorrect file")
require.Equal(t, values["Port"], "9001", "incorrect port number")
require.Equal(t, values["Scheme"], "http", "incorrect scheme")
require.Equal(t, values["Hostname"], "localhost:9001", "incorrect hostname")
baseURL = "https://example.com"
parsed, _ = urlutil.Parse(baseURL)
values = GenerateVariables(parsed, false, nil)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["Host"], "example.com", "incorrect domain name")
require.Equal(t, values["RootURL"], "https://example.com", "incorrect rootURL")
require.Equal(t, values["Path"], "", "incorrect path")
require.Equal(t, values["Port"], "443", "incorrect port number")
require.Equal(t, values["Scheme"], "https", "incorrect scheme")
require.Equal(t, values["Hostname"], "example.com", "incorrect hostname")
baseURL = "ftp://foobar.com/"
parsed, _ = urlutil.Parse(baseURL)
values = GenerateVariables(parsed, false, nil)
require.Equal(t, values["BaseURL"], parsed.String(), "incorrect baseurl")
require.Equal(t, values["Host"], "foobar.com", "incorrect domain name")
require.Equal(t, values["RootURL"], "ftp://foobar.com", "incorrect rootURL")
require.Equal(t, values["Path"], "/", "incorrect path")
require.Equal(t, values["Port"], "", "incorrect port number") // Unsupported protocol results in a blank port
require.Equal(t, values["Scheme"], "ftp", "incorrect scheme")
require.Equal(t, values["Hostname"], "foobar.com", "incorrect hostname")
baseURL = "http://scanme.sh"
ctxArgs := contextargs.NewWithInput(context.Background(), baseURL)
ctxArgs.MetaInput.CustomIP = "1.2.3.4"
values = GenerateVariablesWithContextArgs(ctxArgs, true)
require.Equal(t, values["BaseURL"], baseURL, "incorrect baseurl")
require.Equal(t, values["Host"], "scanme.sh", "incorrect domain name")
require.Equal(t, values["RootURL"], "http://scanme.sh", "incorrect rootURL")
require.Equal(t, values["Path"], "", "incorrect path")
require.Equal(t, values["Port"], "80", "incorrect port number")
require.Equal(t, values["Scheme"], "http", "incorrect scheme")
require.Equal(t, values["Hostname"], "scanme.sh", "incorrect hostname")
require.Equal(t, values["ip"], "1.2.3.4", "incorrect ip")
}
func TestGenerateDNSVariables(t *testing.T) {
vars := GenerateDNSVariables("www.projectdiscovery.io")
require.Equal(t, map[string]interface{}{
"FQDN": "www.projectdiscovery.io",
"RDN": "projectdiscovery.io",
"DN": "projectdiscovery",
"TLD": "io",
"SD": "www",
}, vars, "could not get dns variables")
}
func TestGenerateVariablesForDNS(t *testing.T) {
vars := GenerateVariables("www.projectdiscovery.io", false, nil)
expected := map[string]interface{}{
"FQDN": "www.projectdiscovery.io",
"RDN": "projectdiscovery.io",
"DN": "projectdiscovery",
"TLD": "io",
"SD": "www",
}
checkResults(t, vars, expected)
}
func TestGenerateVariablesForTCP(t *testing.T) {
vars := GenerateVariables("127.0.0.1:5431", false, nil)
expected := map[string]interface{}{
"Host": "127.0.0.1",
"Port": "5431",
"Hostname": "127.0.0.1:5431",
}
checkResults(t, vars, expected)
vars = GenerateVariables("127.0.0.1", false, nil)
expected = map[string]interface{}{
"Host": "127.0.0.1",
"Hostname": "127.0.0.1",
}
checkResults(t, vars, expected)
}
func TestGenerateWhoISVariables(t *testing.T) {
vars := GenerateVariables("https://example.com", false, nil)
expected := map[string]interface{}{
"Host": "example.com", "Hostname": "example.com", "Input": "https://example.com",
}
checkResults(t, vars, expected)
vars = GenerateVariables("https://example.com:8080", false, nil)
expected = map[string]interface{}{
"Host": "example.com", "Hostname": "example.com:8080", "Input": "https://example.com:8080",
}
checkResults(t, vars, expected)
}
func TestGetWebsocketVariables(t *testing.T) {
baseURL := "ws://127.0.0.1:40221"
parsed, _ := urlutil.Parse(baseURL)
vars := GenerateVariables(parsed, false, nil)
expected := map[string]interface{}{
"Host": "127.0.0.1",
"Hostname": "127.0.0.1:40221",
"Scheme": "ws",
"Path": "",
}
checkResults(t, vars, expected)
baseURL = "ws://127.0.0.1:40221/test?var=test"
parsed, _ = urlutil.Parse(baseURL)
vars = GenerateVariables(parsed, false, nil)
expected = map[string]interface{}{
"Host": "127.0.0.1",
"Hostname": "127.0.0.1:40221",
"Scheme": "ws",
"Path": "/test?var=test",
}
checkResults(t, vars, expected)
}
// checkResults returns true if mapSubset is a subset of mapSet otherwise false
func checkResults(t *testing.T, mapSet interface{}, mapSubset interface{}) {
got := reflect.ValueOf(mapSet)
expected := reflect.ValueOf(mapSubset)
require.Greater(t, len(expected.MapKeys()), 0, "failed expected value is empty")
require.Greater(t, len(got.MapKeys()), 0, "failed expected value is empty")
require.LessOrEqual(t, len(expected.MapKeys()), len(got.MapKeys()), "failed return value more than expected")
iterMapSubset := expected.MapRange()
for iterMapSubset.Next() {
k := iterMapSubset.Key()
v := iterMapSubset.Value()
value := got.MapIndex(k)
if !value.IsValid() || v.Interface() != value.Interface() {
require.Equal(t, value, v, "failed return value is not equal to expected")
}
}
}