Path: blob/dev/pkg/protocols/http/build_request_test.go
2070 views
package http12import (3"context"4"testing"5"time"67"github.com/stretchr/testify/require"89"github.com/projectdiscovery/nuclei/v3/pkg/model"10"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"11"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"12"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"13"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"14"github.com/projectdiscovery/nuclei/v3/pkg/testutils"15)1617func TestMakeRequestFromModal(t *testing.T) {18options := testutils.DefaultOptions1920testutils.Init(options)21templateID := "testing-http"22request := &Request{23ID: templateID,24Name: "testing",25Path: []string{"{{BaseURL}}/login.php"},26Method: HTTPMethodTypeHolder{MethodType: HTTPPost},27Body: "username=test&password=pass",28Headers: map[string]string{29"Content-Type": "application/x-www-form-urlencoded",30"Content-Length": "1",31},32}33executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{34ID: templateID,35Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},36})37err := request.Compile(executerOpts)38require.Nil(t, err, "could not compile http request")3940generator := request.newGenerator(false)41inputData, payloads, _ := generator.nextValue()42req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})43require.Nil(t, err, "could not make http request")44if req.request.URL == nil {45t.Fatalf("url is nil in generator make")46}47bodyBytes, _ := req.request.BodyBytes()48require.Equal(t, "/login.php", req.request.Path, "could not get correct request path")49require.Equal(t, "username=test&password=pass", string(bodyBytes), "could not get correct request body")50}5152func TestMakeRequestFromModalTrimSuffixSlash(t *testing.T) {53options := testutils.DefaultOptions5455testutils.Init(options)56templateID := "testing-http"57request := &Request{58ID: templateID,59Name: "testing",60Path: []string{"{{BaseURL}}?query=example"},61Method: HTTPMethodTypeHolder{MethodType: HTTPGet},62}63executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{64ID: templateID,65Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},66})67err := request.Compile(executerOpts)68require.Nil(t, err, "could not compile http request")6970generator := request.newGenerator(false)71inputData, payloads, _ := generator.nextValue()72req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test.php"), inputData, payloads, map[string]interface{}{})73require.Nil(t, err, "could not make http request")74require.Equal(t, "https://example.com/test.php?query=example", req.request.String(), "could not get correct request path")7576generator = request.newGenerator(false)77inputData, payloads, _ = generator.nextValue()78req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test/"), inputData, payloads, map[string]interface{}{})79require.Nil(t, err, "could not make http request")80require.Equal(t, "https://example.com/test/?query=example", req.request.String(), "could not get correct request path")81}8283func TestMakeRequestFromRawWithPayloads(t *testing.T) {84options := testutils.DefaultOptions8586testutils.Init(options)87templateID := "testing-http"88request := &Request{89ID: templateID,90Name: "testing",91Payloads: map[string]interface{}{92"username": []string{"admin"},93"password": []string{"admin", "guest", "password", "test", "12345", "123456"},94},95AttackType: generators.AttackTypeHolder{Value: generators.ClusterBombAttack},96Raw: []string{`GET /manager/html HTTP/1.197Host: {{Hostname}}98User-Agent: Nuclei - Open-source project (github.com/projectdiscovery/nuclei)99Connection: close100Authorization: Basic {{username + ':' + password}}101Accept-Encoding: gzip`},102}103executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{104ID: templateID,105Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},106})107err := request.Compile(executerOpts)108require.Nil(t, err, "could not compile http request")109110generator := request.newGenerator(false)111inputData, payloads, _ := generator.nextValue()112req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})113require.Nil(t, err, "could not make http request")114authorization := req.request.Header.Get("Authorization")115require.Equal(t, "Basic admin:admin", authorization, "could not get correct authorization headers from raw")116117inputData, payloads, _ = generator.nextValue()118req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})119require.Nil(t, err, "could not make http request")120authorization = req.request.Header.Get("Authorization")121require.Equal(t, "Basic admin:guest", authorization, "could not get correct authorization headers from raw")122}123124func TestMakeRequestFromRawPayloadExpressions(t *testing.T) {125options := testutils.DefaultOptions126127testutils.Init(options)128templateID := "testing-http"129request := &Request{130ID: templateID,131Name: "testing",132Payloads: map[string]interface{}{133"username": []string{"admin"},134"password": []string{"admin", "guest", "password", "test", "12345", "123456"},135},136AttackType: generators.AttackTypeHolder{Value: generators.ClusterBombAttack},137Raw: []string{`GET /manager/html HTTP/1.1138Host: {{Hostname}}139User-Agent: Nuclei - Open-source project (github.com/projectdiscovery/nuclei)140Connection: close141Authorization: Basic {{base64(username + ':' + password)}}142Accept-Encoding: gzip`},143}144executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{145ID: templateID,146Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},147})148err := request.Compile(executerOpts)149require.Nil(t, err, "could not compile http request")150151generator := request.newGenerator(false)152inputData, payloads, _ := generator.nextValue()153req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})154require.Nil(t, err, "could not make http request")155authorization := req.request.Header.Get("Authorization")156require.Equal(t, "Basic YWRtaW46YWRtaW4=", authorization, "could not get correct authorization headers from raw")157158inputData, payloads, _ = generator.nextValue()159req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})160require.Nil(t, err, "could not make http request")161authorization = req.request.Header.Get("Authorization")162require.Equal(t, "Basic YWRtaW46Z3Vlc3Q=", authorization, "could not get correct authorization headers from raw")163}164165func TestMakeRequestFromModelUniqueInteractsh(t *testing.T) {166167options := testutils.DefaultOptions168169testutils.Init(options)170templateID := "testing-unique-interactsh"171request := &Request{172ID: templateID,173Name: "testing",174Path: []string{"{{BaseURL}}/?u=http://{{interactsh-url}}/&href=http://{{interactsh-url}}/&action=http://{{interactsh-url}}/&host={{interactsh-url}}"},175Method: HTTPMethodTypeHolder{MethodType: HTTPGet},176}177executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{178ID: templateID,179Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},180})181err := request.Compile(executerOpts)182require.Nil(t, err, "could not compile http request")183184generator := request.newGenerator(false)185186generator.options.Interactsh, err = interactsh.New(&interactsh.Options{187ServerURL: options.InteractshURL,188CacheSize: options.InteractionsCacheSize,189Eviction: time.Duration(options.InteractionsEviction) * time.Second,190CooldownPeriod: time.Duration(options.InteractionsCoolDownPeriod) * time.Second,191PollDuration: time.Duration(options.InteractionsPollDuration) * time.Second,192DisableHttpFallback: true,193})194require.Nil(t, err, "could not create interactsh client")195196inputData, payloads, _ := generator.nextValue()197got, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com"), inputData, payloads, map[string]interface{}{})198require.Nil(t, err, "could not make http request")199200// check if all the interactsh markers are replaced with unique urls201require.NotContains(t, got.request.String(), "{{interactsh-url}}", "could not get correct interactsh url")202// check the length of returned urls203require.Equal(t, len(got.interactshURLs), 4, "could not get correct interactsh url")204// check if the interactsh urls are unique205require.True(t, areUnique(got.interactshURLs), "interactsh urls are not unique")206}207208// areUnique checks if the elements of string slice are unique209func areUnique(elements []string) bool {210encountered := map[string]bool{}211for v := range elements {212if encountered[elements[v]] {213return false214}215encountered[elements[v]] = true216}217return true218}219220221