Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/file/operators_test.go
2070 views
1
package file
2
3
import (
4
"testing"
5
6
"github.com/stretchr/testify/require"
7
8
"github.com/projectdiscovery/nuclei/v3/pkg/model"
9
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
10
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
11
"github.com/projectdiscovery/nuclei/v3/pkg/operators/extractors"
12
"github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers"
13
"github.com/projectdiscovery/nuclei/v3/pkg/output"
14
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
15
)
16
17
func newMockOperator() operators.Operators {
18
operators := operators.Operators{
19
Matchers: []*matchers.Matcher{
20
{
21
Type: matchers.MatcherTypeHolder{
22
MatcherType: matchers.WordsMatcher,
23
},
24
},
25
},
26
}
27
return operators
28
}
29
30
func TestResponseToDSLMap(t *testing.T) {
31
options := testutils.DefaultOptions
32
33
testutils.Init(options)
34
templateID := "testing-file"
35
request := &Request{
36
ID: templateID,
37
MaxSize: "1Gb",
38
NoRecursive: false,
39
Extensions: []string{"*", ".lock"},
40
DenyList: []string{".go"},
41
Operators: newMockOperator(),
42
}
43
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
44
ID: templateID,
45
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
46
})
47
err := request.Compile(executerOpts)
48
require.Nil(t, err, "could not compile file request")
49
50
resp := "test-data\r\n"
51
event := request.responseToDSLMap(resp, "one.one.one.one", "one.one.one.one")
52
require.Len(t, event, 7, "could not get correct number of items in dsl map")
53
require.Equal(t, resp, event["raw"], "could not get correct resp")
54
}
55
56
func TestFileOperatorMatch(t *testing.T) {
57
options := testutils.DefaultOptions
58
59
testutils.Init(options)
60
templateID := "testing-file"
61
request := &Request{
62
ID: templateID,
63
MaxSize: "1Gb",
64
NoRecursive: false,
65
Extensions: []string{"*", ".lock"},
66
DenyList: []string{".go"},
67
Operators: newMockOperator(),
68
}
69
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
70
ID: templateID,
71
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
72
})
73
err := request.Compile(executerOpts)
74
require.Nil(t, err, "could not compile file request")
75
76
resp := "test-data\r\n1.1.1.1\r\n"
77
event := request.responseToDSLMap(resp, "one.one.one.one", "one.one.one.one")
78
require.Len(t, event, 7, "could not get correct number of items in dsl map")
79
require.Equal(t, resp, event["raw"], "could not get correct resp")
80
81
t.Run("valid", func(t *testing.T) {
82
matcher := &matchers.Matcher{
83
Part: "raw",
84
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
85
Words: []string{"1.1.1.1"},
86
}
87
err = matcher.CompileMatchers()
88
require.Nil(t, err, "could not compile matcher")
89
90
isMatched, matched := request.Match(event, matcher)
91
require.True(t, isMatched, "could not match valid response")
92
require.Equal(t, matcher.Words, matched)
93
})
94
95
t.Run("negative", func(t *testing.T) {
96
matcher := &matchers.Matcher{
97
Part: "raw",
98
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
99
Negative: true,
100
Words: []string{"random"},
101
}
102
err := matcher.CompileMatchers()
103
require.Nil(t, err, "could not compile negative matcher")
104
105
isMatched, matched := request.Match(event, matcher)
106
require.True(t, isMatched, "could not match valid negative response matcher")
107
require.Equal(t, []string{}, matched)
108
})
109
110
t.Run("invalid", func(t *testing.T) {
111
matcher := &matchers.Matcher{
112
Part: "raw",
113
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
114
Words: []string{"random"},
115
}
116
err := matcher.CompileMatchers()
117
require.Nil(t, err, "could not compile matcher")
118
119
isMatched, matched := request.Match(event, matcher)
120
require.False(t, isMatched, "could match invalid response matcher")
121
require.Equal(t, []string{}, matched)
122
})
123
124
t.Run("caseInsensitive", func(t *testing.T) {
125
resp := "TEST-DATA\r\n1.1.1.1\r\n"
126
event := request.responseToDSLMap(resp, "one.one.one.one", "one.one.one.one")
127
require.Len(t, event, 7, "could not get correct number of items in dsl map")
128
require.Equal(t, resp, event["raw"], "could not get correct resp")
129
130
matcher := &matchers.Matcher{
131
Part: "raw",
132
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
133
Words: []string{"TeSt-DaTA"},
134
CaseInsensitive: true,
135
}
136
err = matcher.CompileMatchers()
137
require.Nil(t, err, "could not compile matcher")
138
139
isMatched, matched := request.Match(event, matcher)
140
require.True(t, isMatched, "could not match valid response")
141
require.Equal(t, []string{"test-data"}, matched)
142
})
143
}
144
145
func TestFileOperatorExtract(t *testing.T) {
146
options := testutils.DefaultOptions
147
148
testutils.Init(options)
149
templateID := "testing-file"
150
request := &Request{
151
ID: templateID,
152
MaxSize: "1Gb",
153
NoRecursive: false,
154
Extensions: []string{"*", ".lock"},
155
DenyList: []string{".go"},
156
Operators: newMockOperator(),
157
}
158
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
159
ID: templateID,
160
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
161
})
162
err := request.Compile(executerOpts)
163
require.Nil(t, err, "could not compile file request")
164
165
resp := "test-data\r\n1.1.1.1\r\n"
166
event := request.responseToDSLMap(resp, "one.one.one.one", "one.one.one.one")
167
require.Len(t, event, 7, "could not get correct number of items in dsl map")
168
require.Equal(t, resp, event["raw"], "could not get correct resp")
169
170
t.Run("extract", func(t *testing.T) {
171
extractor := &extractors.Extractor{
172
Part: "raw",
173
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
174
Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
175
}
176
err = extractor.CompileExtractors()
177
require.Nil(t, err, "could not compile extractor")
178
179
data := request.Extract(event, extractor)
180
require.Greater(t, len(data), 0, "could not extractor valid response")
181
require.Equal(t, map[string]struct{}{"1.1.1.1": {}}, data, "could not extract correct data")
182
})
183
184
t.Run("kval", func(t *testing.T) {
185
extractor := &extractors.Extractor{
186
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.KValExtractor},
187
KVal: []string{"raw"},
188
}
189
err = extractor.CompileExtractors()
190
require.Nil(t, err, "could not compile kval extractor")
191
192
data := request.Extract(event, extractor)
193
require.Greater(t, len(data), 0, "could not extractor kval valid response")
194
require.Equal(t, map[string]struct{}{resp: {}}, data, "could not extract correct kval data")
195
})
196
}
197
198
func TestFileMakeResultWithOrMatcher(t *testing.T) {
199
expectedValue := []string{"1.1.1.1"}
200
namedMatcherName := "test"
201
202
finalEvent := testFileMakeResultOperators(t, "or")
203
require.Equal(t, namedMatcherName, finalEvent.Results[0].MatcherName)
204
require.Equal(t, expectedValue, finalEvent.OperatorsResult.Matches[namedMatcherName], "could not get matched value")
205
}
206
207
func TestFileMakeResultWithAndMatcher(t *testing.T) {
208
finalEvent := testFileMakeResultOperators(t, "and")
209
require.Equal(t, "", finalEvent.Results[0].MatcherName)
210
require.Empty(t, finalEvent.OperatorsResult.Matches)
211
}
212
213
func testFileMakeResultOperators(t *testing.T, matcherCondition string) *output.InternalWrappedEvent {
214
expectedValue := []string{"1.1.1.1"}
215
namedMatcherName := "test"
216
matcher := []*matchers.Matcher{
217
{
218
Part: "raw",
219
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
220
Words: expectedValue,
221
},
222
{
223
Name: namedMatcherName,
224
Part: "raw",
225
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
226
Words: expectedValue,
227
},
228
}
229
230
expectedValues := map[string][]string{
231
"word-1": expectedValue,
232
namedMatcherName: expectedValue,
233
}
234
235
finalEvent := testFileMakeResult(t, matcher, matcherCondition, true)
236
for matcherName, matchedValues := range expectedValues {
237
var matchesOne = false
238
for i := 0; i <= len(expectedValue); i++ {
239
resultEvent := finalEvent.Results[i]
240
if matcherName == resultEvent.MatcherName {
241
matchesOne = true
242
}
243
}
244
require.True(t, matchesOne)
245
require.Equal(t, matchedValues, finalEvent.OperatorsResult.Matches[matcherName], "could not get matched value")
246
}
247
248
finalEvent = testFileMakeResult(t, matcher, matcherCondition, false)
249
require.Equal(t, 1, len(finalEvent.Results))
250
return finalEvent
251
}
252
253
func testFileMakeResult(t *testing.T, matchers []*matchers.Matcher, matcherCondition string, isDebug bool) *output.InternalWrappedEvent {
254
options := testutils.DefaultOptions
255
256
testutils.Init(options)
257
templateID := "testing-file"
258
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
259
ID: templateID,
260
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
261
})
262
request := &Request{
263
ID: templateID,
264
MaxSize: "1Gb",
265
NoRecursive: false,
266
Extensions: []string{"*", ".lock"},
267
DenyList: []string{".go"},
268
Operators: operators.Operators{
269
MatchersCondition: matcherCondition,
270
Matchers: matchers,
271
Extractors: []*extractors.Extractor{{
272
Part: "raw",
273
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
274
Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
275
}},
276
},
277
options: executerOpts,
278
}
279
err := request.Compile(executerOpts)
280
require.Nil(t, err, "could not compile file request")
281
282
matchedFileName := "test.txt"
283
fileContent := "test-data\r\n1.1.1.1\r\n"
284
285
event := request.responseToDSLMap(fileContent, "/tmp", matchedFileName)
286
require.Len(t, event, 7, "could not get correct number of items in dsl map")
287
require.Equal(t, fileContent, event["raw"], "could not get correct resp")
288
289
finalEvent := &output.InternalWrappedEvent{InternalEvent: event}
290
if request.CompiledOperators != nil {
291
result, ok := request.CompiledOperators.Execute(event, request.Match, request.Extract, isDebug)
292
if ok && result != nil {
293
finalEvent.OperatorsResult = result
294
finalEvent.Results = request.MakeResultEvent(finalEvent)
295
}
296
}
297
resultEvent := finalEvent.Results[0]
298
require.Equal(t, "1.1.1.1", resultEvent.ExtractedResults[0], "could not get correct extracted results")
299
require.Equal(t, matchedFileName, resultEvent.Matched, "could not get matched value")
300
301
return finalEvent
302
}
303
304