2021-02-03 02:09:45 +05:30
package dns
import (
"net"
"strconv"
"testing"
"github.com/miekg/dns"
2021-07-19 21:04:08 +03:00
"github.com/stretchr/testify/require"
"github.com/projectdiscovery/nuclei/v2/pkg/model"
2021-09-03 16:48:39 +03:00
"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
2021-02-03 02:09:45 +05:30
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
"github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors"
"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
2021-11-05 03:01:41 +05:30
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
2021-02-03 02:09:45 +05:30
)
func TestResponseToDSLMap ( t * testing . T ) {
options := testutils . DefaultOptions
2021-11-23 13:09:22 +05:30
recursion := false
2021-02-03 02:09:45 +05:30
testutils . Init ( options )
templateID := "testing-dns"
request := & Request {
2021-11-18 07:47:34 -06:00
RequestType : DNSRequestTypeHolder { DNSRequestType : A } ,
2021-11-03 19:53:45 +05:30
Class : "INET" ,
Retries : 5 ,
ID : templateID ,
2021-11-23 13:09:22 +05:30
Recursion : & recursion ,
2021-11-03 19:53:45 +05:30
Name : "{{FQDN}}" ,
2021-02-03 02:09:45 +05:30
}
executerOpts := testutils . NewMockExecuterOptions ( options , & testutils . TemplateInfo {
ID : templateID ,
2021-09-03 16:48:39 +03:00
Info : model . Info { SeverityHolder : severity . Holder { Severity : severity . Low } , Name : "test" } ,
2021-02-03 02:09:45 +05:30
} )
err := request . Compile ( executerOpts )
require . Nil ( t , err , "could not compile dns request" )
req := new ( dns . Msg )
req . Question = append ( req . Question , dns . Question { Name : "one.one.one.one." , Qtype : dns . TypeA , Qclass : dns . ClassINET } )
resp := new ( dns . Msg )
resp . Rcode = dns . RcodeSuccess
2023-05-12 17:29:37 +05:30
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 } } )
2021-02-03 02:09:45 +05:30
2021-11-18 14:52:11 +01:00
event := request . responseToDSLMap ( req , resp , "one.one.one.one" , "one.one.one.one" , nil )
2023-05-02 17:13:11 +05:30
require . Len ( t , event , 15 , "could not get correct number of items in dsl map" )
2021-02-03 02:09:45 +05:30
require . Equal ( t , dns . RcodeSuccess , event [ "rcode" ] , "could not get correct rcode" )
2023-05-12 17:29:37 +05:30
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" )
2021-02-03 02:09:45 +05:30
}
func TestDNSOperatorMatch ( t * testing . T ) {
options := testutils . DefaultOptions
2021-11-23 13:09:22 +05:30
recursion := false
2021-02-03 02:09:45 +05:30
testutils . Init ( options )
templateID := "testing-dns"
request := & Request {
2021-11-18 07:47:34 -06:00
RequestType : DNSRequestTypeHolder { DNSRequestType : A } ,
2021-11-03 19:53:45 +05:30
Class : "INET" ,
Retries : 5 ,
ID : templateID ,
2021-11-23 13:09:22 +05:30
Recursion : & recursion ,
2021-11-03 19:53:45 +05:30
Name : "{{FQDN}}" ,
2021-02-03 02:09:45 +05:30
}
executerOpts := testutils . NewMockExecuterOptions ( options , & testutils . TemplateInfo {
ID : templateID ,
2021-09-03 16:48:39 +03:00
Info : model . Info { SeverityHolder : severity . Holder { Severity : severity . Low } , Name : "test" } ,
2021-02-03 02:09:45 +05:30
} )
err := request . Compile ( executerOpts )
require . Nil ( t , err , "could not compile dns request" )
req := new ( dns . Msg )
req . Question = append ( req . Question , dns . Question { Name : "one.one.one.one." , Qtype : dns . TypeA , Qclass : dns . ClassINET } )
resp := new ( dns . Msg )
resp . Rcode = dns . RcodeSuccess
resp . Answer = append ( resp . Answer , & dns . A { A : net . ParseIP ( "1.1.1.1" ) , Hdr : dns . RR_Header { Name : "one.one.one.one." } } )
2021-11-18 14:52:11 +01:00
event := request . responseToDSLMap ( req , resp , "one.one.one.one" , "one.one.one.one" , nil )
2021-02-03 02:09:45 +05:30
t . Run ( "valid" , func ( t * testing . T ) {
matcher := & matchers . Matcher {
Part : "raw" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . WordsMatcher } ,
2021-02-03 02:09:45 +05:30
Words : [ ] string { "1.1.1.1" } ,
}
err = matcher . CompileMatchers ( )
require . Nil ( t , err , "could not compile matcher" )
2021-09-29 19:43:46 +03:00
isMatch , matched := request . Match ( event , matcher )
require . True ( t , isMatch , "could not match valid response" )
require . Equal ( t , matcher . Words , matched )
2021-02-03 02:09:45 +05:30
} )
t . Run ( "rcode" , func ( t * testing . T ) {
matcher := & matchers . Matcher {
Part : "rcode" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . StatusMatcher } ,
2021-02-03 02:09:45 +05:30
Status : [ ] int { dns . RcodeSuccess } ,
}
err = matcher . CompileMatchers ( )
require . Nil ( t , err , "could not compile rcode matcher" )
2021-09-29 19:43:46 +03:00
isMatched , matched := request . Match ( event , matcher )
require . True ( t , isMatched , "could not match valid rcode response" )
require . Equal ( t , [ ] string { } , matched )
2021-02-03 02:09:45 +05:30
} )
t . Run ( "negative" , func ( t * testing . T ) {
matcher := & matchers . Matcher {
Part : "raw" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . WordsMatcher } ,
2021-02-03 02:09:45 +05:30
Negative : true ,
Words : [ ] string { "random" } ,
}
err := matcher . CompileMatchers ( )
require . Nil ( t , err , "could not compile negative matcher" )
2021-09-29 19:43:46 +03:00
isMatched , matched := request . Match ( event , matcher )
require . True ( t , isMatched , "could not match valid negative response matcher" )
require . Equal ( t , [ ] string { } , matched )
2021-02-03 02:09:45 +05:30
} )
2021-02-03 13:07:24 +05:30
t . Run ( "invalid" , func ( t * testing . T ) {
matcher := & matchers . Matcher {
Part : "raw" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . WordsMatcher } ,
2021-02-03 13:07:24 +05:30
Words : [ ] string { "random" } ,
}
err := matcher . CompileMatchers ( )
require . Nil ( t , err , "could not compile matcher" )
2021-09-29 19:43:46 +03:00
isMatched , matched := request . Match ( event , matcher )
require . False ( t , isMatched , "could match invalid response matcher" )
require . Equal ( t , [ ] string { } , matched )
2021-02-03 13:07:24 +05:30
} )
2021-10-29 19:11:09 +03:00
t . Run ( "caseInsensitive" , func ( t * testing . T ) {
req := new ( dns . Msg )
req . Question = append ( req . Question , dns . Question { Name : "ONE.ONE.ONE.ONE." , Qtype : dns . TypeA , Qclass : dns . ClassINET } )
resp := new ( dns . Msg )
resp . Rcode = dns . RcodeSuccess
resp . Answer = append ( resp . Answer , & dns . A { A : net . ParseIP ( "1.1.1.1" ) , Hdr : dns . RR_Header { Name : "ONE.ONE.ONE.ONE." } } )
2021-11-18 14:52:11 +01:00
event := request . responseToDSLMap ( req , resp , "ONE.ONE.ONE.ONE" , "ONE.ONE.ONE.ONE" , nil )
2021-10-29 19:11:09 +03:00
matcher := & matchers . Matcher {
Part : "raw" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . WordsMatcher } ,
2021-10-29 19:11:09 +03:00
Words : [ ] string { "one.ONE.one.ONE" } ,
CaseInsensitive : true ,
}
err = matcher . CompileMatchers ( )
require . Nil ( t , err , "could not compile matcher" )
isMatch , matched := request . Match ( event , matcher )
require . True ( t , isMatch , "could not match valid response" )
require . Equal ( t , [ ] string { "one.one.one.one" } , matched )
} )
2021-02-03 02:09:45 +05:30
}
func TestDNSOperatorExtract ( t * testing . T ) {
options := testutils . DefaultOptions
2021-11-23 13:09:22 +05:30
recursion := false
2021-02-03 02:09:45 +05:30
testutils . Init ( options )
templateID := "testing-dns"
request := & Request {
2021-11-18 07:47:34 -06:00
RequestType : DNSRequestTypeHolder { DNSRequestType : A } ,
2021-11-03 19:53:45 +05:30
Class : "INET" ,
Retries : 5 ,
ID : templateID ,
2021-11-23 13:09:22 +05:30
Recursion : & recursion ,
2021-11-03 19:53:45 +05:30
Name : "{{FQDN}}" ,
2021-02-03 02:09:45 +05:30
}
executerOpts := testutils . NewMockExecuterOptions ( options , & testutils . TemplateInfo {
ID : templateID ,
2021-09-03 16:48:39 +03:00
Info : model . Info { SeverityHolder : severity . Holder { Severity : severity . Low } , Name : "test" } ,
2021-02-03 02:09:45 +05:30
} )
err := request . Compile ( executerOpts )
require . Nil ( t , err , "could not compile dns request" )
req := new ( dns . Msg )
req . Question = append ( req . Question , dns . Question { Name : "one.one.one.one." , Qtype : dns . TypeA , Qclass : dns . ClassINET } )
resp := new ( dns . Msg )
resp . Rcode = dns . RcodeSuccess
resp . Answer = append ( resp . Answer , & dns . A { A : net . ParseIP ( "1.1.1.1" ) , Hdr : dns . RR_Header { Name : "one.one.one.one." } } )
2021-11-18 14:52:11 +01:00
event := request . responseToDSLMap ( req , resp , "one.one.one.one" , "one.one.one.one" , nil )
2021-02-03 02:09:45 +05:30
t . Run ( "extract" , func ( t * testing . T ) {
extractor := & extractors . Extractor {
Part : "raw" ,
2021-11-25 19:34:01 +05:30
Type : extractors . ExtractorTypeHolder { ExtractorType : extractors . RegexExtractor } ,
2021-02-03 02:09:45 +05:30
Regex : [ ] string { "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" } ,
}
err = extractor . CompileExtractors ( )
require . Nil ( t , err , "could not compile extractor" )
data := request . Extract ( event , extractor )
require . Greater ( t , len ( data ) , 0 , "could not extractor valid response" )
require . Equal ( t , map [ string ] struct { } { "1.1.1.1" : { } } , data , "could not extract correct data" )
} )
t . Run ( "kval" , func ( t * testing . T ) {
extractor := & extractors . Extractor {
2021-11-25 19:34:01 +05:30
Type : extractors . ExtractorTypeHolder { ExtractorType : extractors . KValExtractor } ,
2021-02-03 02:09:45 +05:30
KVal : [ ] string { "rcode" } ,
}
err = extractor . CompileExtractors ( )
require . Nil ( t , err , "could not compile kval extractor" )
data := request . Extract ( event , extractor )
require . Greater ( t , len ( data ) , 0 , "could not extractor kval valid response" )
require . Equal ( t , map [ string ] struct { } { strconv . Itoa ( dns . RcodeSuccess ) : { } } , data , "could not extract correct kval data" )
} )
}
func TestDNSMakeResult ( t * testing . T ) {
options := testutils . DefaultOptions
2021-11-23 13:09:22 +05:30
recursion := false
2021-02-03 02:09:45 +05:30
testutils . Init ( options )
templateID := "testing-dns"
2022-06-24 23:09:27 +05:30
executerOpts := testutils . NewMockExecuterOptions ( options , & testutils . TemplateInfo {
ID : templateID ,
Info : model . Info { SeverityHolder : severity . Holder { Severity : severity . Low } , Name : "test" } ,
} )
2021-02-03 02:09:45 +05:30
request := & Request {
2021-11-18 07:47:34 -06:00
RequestType : DNSRequestTypeHolder { DNSRequestType : A } ,
2021-11-03 19:53:45 +05:30
Class : "INET" ,
Retries : 5 ,
ID : templateID ,
2021-11-23 13:09:22 +05:30
Recursion : & recursion ,
2021-11-03 19:53:45 +05:30
Name : "{{FQDN}}" ,
2021-02-03 02:09:45 +05:30
Operators : operators . Operators {
2021-02-03 17:49:10 +05:30
Matchers : [ ] * matchers . Matcher { {
Name : "test" ,
Part : "raw" ,
2021-11-19 04:54:09 -06:00
Type : matchers . MatcherTypeHolder { MatcherType : matchers . WordsMatcher } ,
2021-02-03 17:49:10 +05:30
Words : [ ] string { "1.1.1.1" } ,
} } ,
Extractors : [ ] * extractors . Extractor { {
Part : "raw" ,
2021-11-25 19:34:01 +05:30
Type : extractors . ExtractorTypeHolder { ExtractorType : extractors . RegexExtractor } ,
2021-02-03 17:49:10 +05:30
Regex : [ ] string { "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" } ,
} } ,
2021-02-03 02:09:45 +05:30
} ,
2022-06-24 23:09:27 +05:30
options : executerOpts ,
2021-02-03 02:09:45 +05:30
}
err := request . Compile ( executerOpts )
require . Nil ( t , err , "could not compile dns request" )
req := new ( dns . Msg )
req . Question = append ( req . Question , dns . Question { Name : "one.one.one.one." , Qtype : dns . TypeA , Qclass : dns . ClassINET } )
resp := new ( dns . Msg )
resp . Rcode = dns . RcodeSuccess
resp . Answer = append ( resp . Answer , & dns . A { A : net . ParseIP ( "1.1.1.1" ) , Hdr : dns . RR_Header { Name : "one.one.one.one." } } )
2021-11-18 14:52:11 +01:00
event := request . responseToDSLMap ( req , resp , "one.one.one.one" , "one.one.one.one" , nil )
2021-02-03 02:09:45 +05:30
finalEvent := & output . InternalWrappedEvent { InternalEvent : event }
if request . CompiledOperators != nil {
2021-10-12 20:06:55 +03:00
result , ok := request . CompiledOperators . Execute ( event , request . Match , request . Extract , false )
2021-02-03 02:09:45 +05:30
if ok && result != nil {
finalEvent . OperatorsResult = result
finalEvent . Results = request . MakeResultEvent ( finalEvent )
}
}
require . Equal ( t , 1 , len ( finalEvent . Results ) , "could not get correct number of results" )
2021-10-12 20:06:55 +03:00
resultEvent := finalEvent . Results [ 0 ]
require . Equal ( t , "test" , resultEvent . MatcherName , "could not get correct matcher name of results" )
require . Equal ( t , "1.1.1.1" , resultEvent . ExtractedResults [ 0 ] , "could not get correct extracted results" )
require . Equal ( t , "one.one.one.one" , resultEvent . Matched , "could not get matched value" )
2021-02-03 02:09:45 +05:30
}