github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/protocols/http/request_test.go (about)

     1  package http
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/projectdiscovery/nuclei/v2/pkg/model"
    12  	"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
    13  	"github.com/projectdiscovery/nuclei/v2/pkg/operators"
    14  	"github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors"
    15  	"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
    16  	"github.com/projectdiscovery/nuclei/v2/pkg/output"
    17  	"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
    18  	"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
    19  )
    20  
    21  func TestHTTPExtractMultipleReuse(t *testing.T) {
    22  	options := testutils.DefaultOptions
    23  
    24  	testutils.Init(options)
    25  	templateID := "testing-http"
    26  	request := &Request{
    27  		ID: templateID,
    28  		Raw: []string{
    29  			`GET /robots.txt HTTP/1.1
    30  			Host: {{Hostname}}
    31  			User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
    32  			Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    33  			Accept-Language: en-US,en;q=0.5
    34  			`,
    35  
    36  			`GET {{endpoint}} HTTP/1.1
    37  			Host: {{Hostname}}
    38  			User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
    39  			Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    40  			Accept-Language: en-US,en;q=0.5
    41  			`,
    42  		},
    43  		Operators: operators.Operators{
    44  			Matchers: []*matchers.Matcher{{
    45  				Part:  "body",
    46  				Type:  matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
    47  				Words: []string{"match /a", "match /b", "match /c"},
    48  			}},
    49  			Extractors: []*extractors.Extractor{{
    50  				Part:     "body",
    51  				Name:     "endpoint",
    52  				Type:     extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
    53  				Regex:    []string{"(?m)/([a-zA-Z0-9-_/\\\\]+)"},
    54  				Internal: true,
    55  			}},
    56  		},
    57  		IterateAll: true,
    58  	}
    59  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    60  		switch r.URL.Path {
    61  		case "/robots.txt":
    62  			_, _ = w.Write([]byte(`User-agent: Googlebot
    63  Disallow: /a
    64  Disallow: /b
    65  Disallow: /c`))
    66  		default:
    67  			_, _ = w.Write([]byte(fmt.Sprintf(`match %v`, r.URL.Path)))
    68  		}
    69  	}))
    70  	defer ts.Close()
    71  
    72  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
    73  		ID:   templateID,
    74  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
    75  	})
    76  
    77  	err := request.Compile(executerOpts)
    78  	require.Nil(t, err, "could not compile network request")
    79  
    80  	var finalEvent *output.InternalWrappedEvent
    81  	var matchCount int
    82  	t.Run("test", func(t *testing.T) {
    83  		metadata := make(output.InternalEvent)
    84  		previous := make(output.InternalEvent)
    85  		ctxArgs := contextargs.NewWithInput(ts.URL)
    86  		err := request.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {
    87  			if event.OperatorsResult != nil && event.OperatorsResult.Matched {
    88  				matchCount++
    89  			}
    90  			finalEvent = event
    91  		})
    92  		require.Nil(t, err, "could not execute network request")
    93  	})
    94  	require.NotNil(t, finalEvent, "could not get event output from request")
    95  	require.Equal(t, 3, matchCount, "could not get correct match count")
    96  }
    97  
    98  func TestDisableTE(t *testing.T) {
    99  	options := testutils.DefaultOptions
   100  
   101  	testutils.Init(options)
   102  	templateID := "http-disable-transfer-encoding"
   103  
   104  	// in raw request format
   105  	request := &Request{
   106  		ID: templateID,
   107  		Raw: []string{
   108  			`POST / HTTP/1.1
   109  			Host: {{Hostname}}
   110  			User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
   111  			Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
   112  			Accept-Language: en-US,en;q=0.5
   113  
   114  			login=1&username=admin&password=admin
   115  			`,
   116  		},
   117  		Operators: operators.Operators{
   118  			Matchers: []*matchers.Matcher{{
   119  				Type:   matchers.MatcherTypeHolder{MatcherType: matchers.StatusMatcher},
   120  				Status: []int{200},
   121  			}},
   122  		},
   123  	}
   124  
   125  	// in base request format
   126  	request2 := &Request{
   127  		ID:     templateID,
   128  		Method: HTTPMethodTypeHolder{MethodType: HTTPPost},
   129  		Path:   []string{"{{BaseURL}}"},
   130  		Body:   "login=1&username=admin&password=admin",
   131  		Operators: operators.Operators{
   132  			Matchers: []*matchers.Matcher{{
   133  				Type:   matchers.MatcherTypeHolder{MatcherType: matchers.StatusMatcher},
   134  				Status: []int{200},
   135  			}},
   136  		},
   137  	}
   138  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   139  		if len(r.TransferEncoding) > 0 || r.ContentLength <= 0 {
   140  			t.Error("Transfer-Encoding header should not be set")
   141  		}
   142  	}))
   143  	defer ts.Close()
   144  
   145  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
   146  		ID:   templateID,
   147  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
   148  	})
   149  
   150  	err := request.Compile(executerOpts)
   151  	require.Nil(t, err, "could not compile http raw request")
   152  
   153  	err = request2.Compile(executerOpts)
   154  	require.Nil(t, err, "could not compile http base request")
   155  
   156  	var finalEvent *output.InternalWrappedEvent
   157  	var matchCount int
   158  	t.Run("test", func(t *testing.T) {
   159  		metadata := make(output.InternalEvent)
   160  		previous := make(output.InternalEvent)
   161  		ctxArgs := contextargs.NewWithInput(ts.URL)
   162  		err := request.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {
   163  			if event.OperatorsResult != nil && event.OperatorsResult.Matched {
   164  				matchCount++
   165  			}
   166  			finalEvent = event
   167  		})
   168  		require.Nil(t, err, "could not execute network request")
   169  	})
   170  
   171  	t.Run("test2", func(t *testing.T) {
   172  		metadata := make(output.InternalEvent)
   173  		previous := make(output.InternalEvent)
   174  		ctxArgs := contextargs.NewWithInput(ts.URL)
   175  		err := request2.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {
   176  			if event.OperatorsResult != nil && event.OperatorsResult.Matched {
   177  				matchCount++
   178  			}
   179  			finalEvent = event
   180  		})
   181  		require.Nil(t, err, "could not execute network request")
   182  	})
   183  
   184  	require.NotNil(t, finalEvent, "could not get event output from request")
   185  	require.Equal(t, 2, matchCount, "could not get correct match count")
   186  }