Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/protocols/dns/operators_test.go
2070 views
1
package dns
2
3
import (
4
"net"
5
"strconv"
6
"testing"
7
8
"github.com/miekg/dns"
9
"github.com/stretchr/testify/require"
10
11
"github.com/projectdiscovery/nuclei/v3/pkg/model"
12
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
13
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
14
"github.com/projectdiscovery/nuclei/v3/pkg/operators/extractors"
15
"github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers"
16
"github.com/projectdiscovery/nuclei/v3/pkg/output"
17
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
18
)
19
20
func TestResponseToDSLMap(t *testing.T) {
21
options := testutils.DefaultOptions
22
23
recursion := false
24
testutils.Init(options)
25
templateID := "testing-dns"
26
request := &Request{
27
RequestType: DNSRequestTypeHolder{DNSRequestType: A},
28
Class: "INET",
29
Retries: 5,
30
ID: templateID,
31
Recursion: &recursion,
32
Name: "{{FQDN}}",
33
}
34
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
35
ID: templateID,
36
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
37
})
38
err := request.Compile(executerOpts)
39
require.Nil(t, err, "could not compile dns request")
40
41
req := new(dns.Msg)
42
req.Question = append(req.Question, dns.Question{Name: "one.one.one.one.", Qtype: dns.TypeA, Qclass: dns.ClassINET})
43
44
resp := new(dns.Msg)
45
resp.Rcode = dns.RcodeSuccess
46
resp.Answer = append(resp.Answer, &dns.A{A: net.ParseIP("1.1.1.1"), Hdr: dns.RR_Header{Name: "one.one.one.one.", Rrtype: dns.TypeA}}, &dns.A{A: net.ParseIP("2.2.2.2"), Hdr: dns.RR_Header{Name: "one.one.one.one.", Rrtype: dns.TypeA}}, &dns.A{A: net.ParseIP("3.3.3.3"), Hdr: dns.RR_Header{Name: "one.one.one.one.", Rrtype: dns.TypeA}})
47
48
event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", nil)
49
require.Len(t, event, 15, "could not get correct number of items in dsl map")
50
require.Equal(t, dns.RcodeSuccess, event["rcode"], "could not get correct rcode")
51
require.ElementsMatch(t, []string{net.ParseIP("1.1.1.1").String(), net.ParseIP("2.2.2.2").String(), net.ParseIP("3.3.3.3").String()}, event["a"], "could not get correct a record")
52
}
53
54
func TestDNSOperatorMatch(t *testing.T) {
55
options := testutils.DefaultOptions
56
57
recursion := false
58
testutils.Init(options)
59
templateID := "testing-dns"
60
request := &Request{
61
RequestType: DNSRequestTypeHolder{DNSRequestType: A},
62
Class: "INET",
63
Retries: 5,
64
ID: templateID,
65
Recursion: &recursion,
66
Name: "{{FQDN}}",
67
}
68
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
69
ID: templateID,
70
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
71
})
72
err := request.Compile(executerOpts)
73
require.Nil(t, err, "could not compile dns request")
74
75
req := new(dns.Msg)
76
req.Question = append(req.Question, dns.Question{Name: "one.one.one.one.", Qtype: dns.TypeA, Qclass: dns.ClassINET})
77
78
resp := new(dns.Msg)
79
resp.Rcode = dns.RcodeSuccess
80
resp.Answer = append(resp.Answer, &dns.A{A: net.ParseIP("1.1.1.1"), Hdr: dns.RR_Header{Name: "one.one.one.one."}})
81
82
event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", nil)
83
84
t.Run("valid", func(t *testing.T) {
85
matcher := &matchers.Matcher{
86
Part: "raw",
87
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
88
Words: []string{"1.1.1.1"},
89
}
90
err = matcher.CompileMatchers()
91
require.Nil(t, err, "could not compile matcher")
92
93
isMatch, matched := request.Match(event, matcher)
94
require.True(t, isMatch, "could not match valid response")
95
require.Equal(t, matcher.Words, matched)
96
})
97
98
t.Run("rcode", func(t *testing.T) {
99
matcher := &matchers.Matcher{
100
Part: "rcode",
101
Type: matchers.MatcherTypeHolder{MatcherType: matchers.StatusMatcher},
102
Status: []int{dns.RcodeSuccess},
103
}
104
err = matcher.CompileMatchers()
105
require.Nil(t, err, "could not compile rcode matcher")
106
107
isMatched, matched := request.Match(event, matcher)
108
require.True(t, isMatched, "could not match valid rcode response")
109
require.Equal(t, []string{}, matched)
110
})
111
112
t.Run("negative", func(t *testing.T) {
113
matcher := &matchers.Matcher{
114
Part: "raw",
115
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
116
Negative: true,
117
Words: []string{"random"},
118
}
119
err := matcher.CompileMatchers()
120
require.Nil(t, err, "could not compile negative matcher")
121
122
isMatched, matched := request.Match(event, matcher)
123
require.True(t, isMatched, "could not match valid negative response matcher")
124
require.Equal(t, []string{}, matched)
125
})
126
127
t.Run("invalid", func(t *testing.T) {
128
matcher := &matchers.Matcher{
129
Part: "raw",
130
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
131
Words: []string{"random"},
132
}
133
err := matcher.CompileMatchers()
134
require.Nil(t, err, "could not compile matcher")
135
136
isMatched, matched := request.Match(event, matcher)
137
require.False(t, isMatched, "could match invalid response matcher")
138
require.Equal(t, []string{}, matched)
139
})
140
141
t.Run("caseInsensitive", func(t *testing.T) {
142
req := new(dns.Msg)
143
req.Question = append(req.Question, dns.Question{Name: "ONE.ONE.ONE.ONE.", Qtype: dns.TypeA, Qclass: dns.ClassINET})
144
145
resp := new(dns.Msg)
146
resp.Rcode = dns.RcodeSuccess
147
resp.Answer = append(resp.Answer, &dns.A{A: net.ParseIP("1.1.1.1"), Hdr: dns.RR_Header{Name: "ONE.ONE.ONE.ONE."}})
148
149
event := request.responseToDSLMap(req, resp, "ONE.ONE.ONE.ONE", "ONE.ONE.ONE.ONE", nil)
150
151
matcher := &matchers.Matcher{
152
Part: "raw",
153
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
154
Words: []string{"one.ONE.one.ONE"},
155
CaseInsensitive: true,
156
}
157
err = matcher.CompileMatchers()
158
require.Nil(t, err, "could not compile matcher")
159
160
isMatch, matched := request.Match(event, matcher)
161
require.True(t, isMatch, "could not match valid response")
162
require.Equal(t, []string{"one.one.one.one"}, matched)
163
})
164
}
165
166
func TestDNSOperatorExtract(t *testing.T) {
167
options := testutils.DefaultOptions
168
169
recursion := false
170
testutils.Init(options)
171
templateID := "testing-dns"
172
request := &Request{
173
RequestType: DNSRequestTypeHolder{DNSRequestType: A},
174
Class: "INET",
175
Retries: 5,
176
ID: templateID,
177
Recursion: &recursion,
178
Name: "{{FQDN}}",
179
}
180
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
181
ID: templateID,
182
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
183
})
184
err := request.Compile(executerOpts)
185
require.Nil(t, err, "could not compile dns request")
186
187
req := new(dns.Msg)
188
req.Question = append(req.Question, dns.Question{Name: "one.one.one.one.", Qtype: dns.TypeA, Qclass: dns.ClassINET})
189
190
resp := new(dns.Msg)
191
resp.Rcode = dns.RcodeSuccess
192
resp.Answer = append(resp.Answer, &dns.A{A: net.ParseIP("1.1.1.1"), Hdr: dns.RR_Header{Name: "one.one.one.one."}})
193
194
event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", nil)
195
196
t.Run("extract", func(t *testing.T) {
197
extractor := &extractors.Extractor{
198
Part: "raw",
199
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
200
Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
201
}
202
err = extractor.CompileExtractors()
203
require.Nil(t, err, "could not compile extractor")
204
205
data := request.Extract(event, extractor)
206
require.Greater(t, len(data), 0, "could not extractor valid response")
207
require.Equal(t, map[string]struct{}{"1.1.1.1": {}}, data, "could not extract correct data")
208
})
209
210
t.Run("kval", func(t *testing.T) {
211
extractor := &extractors.Extractor{
212
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.KValExtractor},
213
KVal: []string{"rcode"},
214
}
215
err = extractor.CompileExtractors()
216
require.Nil(t, err, "could not compile kval extractor")
217
218
data := request.Extract(event, extractor)
219
require.Greater(t, len(data), 0, "could not extractor kval valid response")
220
require.Equal(t, map[string]struct{}{strconv.Itoa(dns.RcodeSuccess): {}}, data, "could not extract correct kval data")
221
})
222
}
223
224
func TestDNSMakeResult(t *testing.T) {
225
options := testutils.DefaultOptions
226
227
recursion := false
228
testutils.Init(options)
229
templateID := "testing-dns"
230
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
231
ID: templateID,
232
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"},
233
})
234
request := &Request{
235
RequestType: DNSRequestTypeHolder{DNSRequestType: A},
236
Class: "INET",
237
Retries: 5,
238
ID: templateID,
239
Recursion: &recursion,
240
Name: "{{FQDN}}",
241
Operators: operators.Operators{
242
Matchers: []*matchers.Matcher{{
243
Name: "test",
244
Part: "raw",
245
Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher},
246
Words: []string{"1.1.1.1"},
247
}},
248
Extractors: []*extractors.Extractor{{
249
Part: "raw",
250
Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.RegexExtractor},
251
Regex: []string{"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"},
252
}},
253
},
254
options: executerOpts,
255
}
256
err := request.Compile(executerOpts)
257
require.Nil(t, err, "could not compile dns request")
258
259
req := new(dns.Msg)
260
req.Question = append(req.Question, dns.Question{Name: "one.one.one.one.", Qtype: dns.TypeA, Qclass: dns.ClassINET})
261
262
resp := new(dns.Msg)
263
resp.Rcode = dns.RcodeSuccess
264
resp.Answer = append(resp.Answer, &dns.A{A: net.ParseIP("1.1.1.1"), Hdr: dns.RR_Header{Name: "one.one.one.one."}})
265
266
event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", nil)
267
finalEvent := &output.InternalWrappedEvent{InternalEvent: event}
268
if request.CompiledOperators != nil {
269
result, ok := request.CompiledOperators.Execute(event, request.Match, request.Extract, false)
270
if ok && result != nil {
271
finalEvent.OperatorsResult = result
272
finalEvent.Results = request.MakeResultEvent(finalEvent)
273
}
274
}
275
require.Equal(t, 1, len(finalEvent.Results), "could not get correct number of results")
276
resultEvent := finalEvent.Results[0]
277
require.Equal(t, "test", resultEvent.MatcherName, "could not get correct matcher name of results")
278
require.Equal(t, "1.1.1.1", resultEvent.ExtractedResults[0], "could not get correct extracted results")
279
require.Equal(t, "one.one.one.one", resultEvent.Matched, "could not get matched value")
280
}
281
282