github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/protocols/network/operators_test.go (about)

     1  package network
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/projectdiscovery/nuclei/v2/pkg/model"
     9  	"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
    10  	"github.com/projectdiscovery/nuclei/v2/pkg/operators"
    11  	"github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors"
    12  	"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
    13  	"github.com/projectdiscovery/nuclei/v2/pkg/output"
    14  	"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
    15  )
    16  
    17  func TestResponseToDSLMap(t *testing.T) {
    18  	options := testutils.DefaultOptions
    19  
    20  	testutils.Init(options)
    21  	templateID := "testing-network"
    22  	request := &Request{
    23  		ID:       templateID,
    24  		Address:  []string{"{{Hostname}}"},
    25  		ReadSize: 1024,
    26  		Inputs:   []*Input{{Data: "test-data\r\n"}},
    27  	}
    28  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
    29  		ID:   templateID,
    30  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
    31  	})
    32  	err := request.Compile(executerOpts)
    33  	require.Nil(t, err, "could not compile network request")
    34  
    35  	req := "test-data\r\n"
    36  	resp := "resp-data\r\n"
    37  	event := request.responseToDSLMap(req, resp, "test", "one.one.one.one", "one.one.one.one")
    38  	require.Len(t, event, 9, "could not get correct number of items in dsl map")
    39  	require.Equal(t, resp, event["data"], "could not get correct resp")
    40  }
    41  
    42  func TestNetworkOperatorMatch(t *testing.T) {
    43  	options := testutils.DefaultOptions
    44  
    45  	testutils.Init(options)
    46  	templateID := "testing-network"
    47  	request := &Request{
    48  		ID:       templateID,
    49  		Address:  []string{"{{Hostname}}"},
    50  		ReadSize: 1024,
    51  		Inputs:   []*Input{{Data: "test-data\r\n"}},
    52  	}
    53  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
    54  		ID:   templateID,
    55  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
    56  	})
    57  	err := request.Compile(executerOpts)
    58  	require.Nil(t, err, "could not compile network request")
    59  
    60  	req := "test-data\r\n"
    61  	resp := "resp-data\r\nSTAT \r\n"
    62  	event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", "test")
    63  
    64  	t.Run("valid", func(t *testing.T) {
    65  		matcher := &matchers.Matcher{
    66  			Part:  "body",
    67  			Type:  matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
    68  			Words: []string{"STAT "},
    69  		}
    70  		err = matcher.CompileMatchers()
    71  		require.Nil(t, err, "could not compile matcher")
    72  
    73  		isMatched, matched := request.Match(event, matcher)
    74  		require.True(t, isMatched, "could not match valid response")
    75  		require.Equal(t, matcher.Words, matched)
    76  	})
    77  
    78  	t.Run("negative", func(t *testing.T) {
    79  		matcher := &matchers.Matcher{
    80  			Part:     "data",
    81  			Type:     matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
    82  			Negative: true,
    83  			Words:    []string{"random"},
    84  		}
    85  		err := matcher.CompileMatchers()
    86  		require.Nil(t, err, "could not compile negative matcher")
    87  
    88  		isMatched, matched := request.Match(event, matcher)
    89  		require.True(t, isMatched, "could not match valid negative response matcher")
    90  		require.Equal(t, []string{}, matched)
    91  	})
    92  
    93  	t.Run("invalid", func(t *testing.T) {
    94  		matcher := &matchers.Matcher{
    95  			Part:  "data",
    96  			Type:  matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
    97  			Words: []string{"random"},
    98  		}
    99  		err := matcher.CompileMatchers()
   100  		require.Nil(t, err, "could not compile matcher")
   101  
   102  		isMatched, matched := request.Match(event, matcher)
   103  		require.False(t, isMatched, "could match invalid response matcher")
   104  		require.Equal(t, []string{}, matched)
   105  	})
   106  
   107  	t.Run("caseInsensitive", func(t *testing.T) {
   108  		matcher := &matchers.Matcher{
   109  			Part:            "body",
   110  			Type:            matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
   111  			Words:           []string{"rESp-DAta"},
   112  			CaseInsensitive: true,
   113  		}
   114  		err = matcher.CompileMatchers()
   115  		require.Nil(t, err, "could not compile matcher")
   116  
   117  		req := "TEST-DATA\r\n"
   118  		resp := "RESP-DATA\r\nSTAT \r\n"
   119  		event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", "TEST")
   120  
   121  		isMatched, matched := request.Match(event, matcher)
   122  		require.True(t, isMatched, "could not match valid response")
   123  		require.Equal(t, []string{"resp-data"}, matched)
   124  	})
   125  }
   126  
   127  func TestNetworkOperatorExtract(t *testing.T) {
   128  	options := testutils.DefaultOptions
   129  
   130  	testutils.Init(options)
   131  	templateID := "testing-network"
   132  	request := &Request{
   133  		ID:       templateID,
   134  		Address:  []string{"{{Hostname}}"},
   135  		ReadSize: 1024,
   136  		Inputs:   []*Input{{Data: "test-data\r\n"}},
   137  	}
   138  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
   139  		ID:   templateID,
   140  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
   141  	})
   142  	err := request.Compile(executerOpts)
   143  	require.Nil(t, err, "could not compile network request")
   144  
   145  	req := "test-data\r\n"
   146  	resp := "resp-data\r\nSTAT \r\n1.1.1.1\r\n"
   147  	event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", "test")
   148  
   149  	t.Run("extract", func(t *testing.T) {
   150  		extractor := &extractors.Extractor{
   151  			Part:  "data",
   152  			Type:  extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
   153  			Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
   154  		}
   155  		err = extractor.CompileExtractors()
   156  		require.Nil(t, err, "could not compile extractor")
   157  
   158  		data := request.Extract(event, extractor)
   159  		require.Greater(t, len(data), 0, "could not extractor valid response")
   160  		require.Equal(t, map[string]struct{}{"1.1.1.1": {}}, data, "could not extract correct data")
   161  	})
   162  
   163  	t.Run("kval", func(t *testing.T) {
   164  		extractor := &extractors.Extractor{
   165  			Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.KValExtractor},
   166  			KVal: []string{"request"},
   167  		}
   168  		err = extractor.CompileExtractors()
   169  		require.Nil(t, err, "could not compile kval extractor")
   170  
   171  		data := request.Extract(event, extractor)
   172  		require.Greater(t, len(data), 0, "could not extractor kval valid response")
   173  		require.Equal(t, map[string]struct{}{req: {}}, data, "could not extract correct kval data")
   174  	})
   175  }
   176  
   177  func TestNetworkMakeResult(t *testing.T) {
   178  	options := testutils.DefaultOptions
   179  
   180  	testutils.Init(options)
   181  	templateID := "testing-network"
   182  	request := &Request{
   183  		ID:       templateID,
   184  		Address:  []string{"{{Hostname}}"},
   185  		ReadSize: 1024,
   186  		Inputs:   []*Input{{Data: "test-data\r\n"}},
   187  		Operators: operators.Operators{
   188  			Matchers: []*matchers.Matcher{{
   189  				Name:  "test",
   190  				Part:  "data",
   191  				Type:  matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
   192  				Words: []string{"STAT "},
   193  			}},
   194  			Extractors: []*extractors.Extractor{{
   195  				Part:  "data",
   196  				Type:  extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
   197  				Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
   198  			}},
   199  		},
   200  	}
   201  	executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
   202  		ID:   templateID,
   203  		Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
   204  	})
   205  	err := request.Compile(executerOpts)
   206  	require.Nil(t, err, "could not compile network request")
   207  
   208  	req := "test-data\r\n"
   209  	resp := "resp-data\rSTAT \r\n1.1.1.1\n"
   210  	event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", "test")
   211  	finalEvent := &output.InternalWrappedEvent{InternalEvent: event}
   212  	event["ip"] = "192.168.1.1"
   213  	if request.CompiledOperators != nil {
   214  		result, ok := request.CompiledOperators.Execute(event, request.Match, request.Extract, false)
   215  		if ok && result != nil {
   216  			finalEvent.OperatorsResult = result
   217  			finalEvent.Results = request.MakeResultEvent(finalEvent)
   218  		}
   219  	}
   220  	require.Equal(t, 1, len(finalEvent.Results), "could not get correct number of results")
   221  	require.Equal(t, "test", finalEvent.Results[0].MatcherName, "could not get correct matcher name of results")
   222  	require.Equal(t, "1.1.1.1", finalEvent.Results[0].ExtractedResults[0], "could not get correct extracted results")
   223  }