Expose DNS fields for matchers and extractors (#3613)

* Extend dns extractor to dns answer records

* add test template

* Ignore error for dns variables are not found

* Add all the records of answer section

* Fixed the wrong typecasting
dev
Shubham Rasal 2023-05-02 17:13:11 +05:30 committed by GitHub
parent d55ad995d0
commit f640187709
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 9 deletions

View File

@ -0,0 +1,23 @@
id: dns-template
info:
name: basic dns template
author: pdteam
severity: info
dns:
- name: "{{FQDN}}"
type: CNAME
matchers:
- type: dsl
dsl:
- "rcode == 0"
extractors:
- type: dsl
dsl:
- rcode
- cname
- a
- aaaa

View File

@ -5,11 +5,12 @@ import (
)
var dnsTestCases = map[string]testutils.TestCase{
"dns/basic.yaml": &dnsBasic{},
"dns/ptr.yaml": &dnsPtr{},
"dns/caa.yaml": &dnsCAA{},
"dns/tlsa.yaml": &dnsTLSA{},
"dns/variables.yaml": &dnsVariables{},
"dns/basic.yaml": &dnsBasic{},
"dns/ptr.yaml": &dnsPtr{},
"dns/caa.yaml": &dnsCAA{},
"dns/tlsa.yaml": &dnsTLSA{},
"dns/variables.yaml": &dnsVariables{},
"dns/dsl-matcher-variable.yaml": &dnsDSLMatcherVariable{},
}
type dnsBasic struct{}
@ -66,3 +67,14 @@ func (h *dnsVariables) Execute(filePath string) error {
}
return expectResultsCount(results, 1)
}
type dnsDSLMatcherVariable struct{}
// Execute executes a test case and returns an error if occurred
func (h *dnsDSLMatcherVariable) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "one.one.one.one", debug)
if err != nil {
return err
}
return expectResultsCount(results, 1)
}

View File

@ -174,7 +174,9 @@ func (e *Extractor) ExtractDSL(data map[string]interface{}) map[string]struct{}
for _, compiledExpression := range e.dslCompiled {
result, err := compiledExpression.Evaluate(data)
if err != nil {
// ignore errors that are related to missing parameters
// eg: dns dsl can have all the parameters that are not present
if err != nil && !strings.HasPrefix(err.Error(), "No parameter") {
return results
}

View File

@ -13,6 +13,7 @@ import (
"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
"github.com/projectdiscovery/retryabledns"
)
@ -79,7 +80,7 @@ func (request *Request) getMatchPart(part string, data output.InternalEvent) (in
// responseToDSLMap converts a DNS response to a map for use in DSL matching
func (request *Request) responseToDSLMap(req, resp *dns.Msg, host, matched string, traceData *retryabledns.TraceData) output.InternalEvent {
return output.InternalEvent{
ret := output.InternalEvent{
"host": host,
"matched": matched,
"request": req.String(),
@ -95,6 +96,7 @@ func (request *Request) responseToDSLMap(req, resp *dns.Msg, host, matched strin
"type": request.Type().String(),
"trace": traceToString(traceData, false),
}
return generators.MergeMaps(ret, recordsKeyValue(resp.Answer))
}
// MakeResultEvent creates a result event from internal wrapped event
@ -147,3 +149,23 @@ func traceToString(traceData *retryabledns.TraceData, withSteps bool) string {
}
return buffer.String()
}
func recordsKeyValue(resourceRecords []dns.RR) output.InternalEvent {
var oe = make(output.InternalEvent)
for _, resourceRecord := range resourceRecords {
key := strings.ToLower(dns.TypeToString[resourceRecord.Header().Rrtype])
value := strings.ReplaceAll(resourceRecord.String(), resourceRecord.Header().String(), "")
if preVal, ok := oe[key]; ok {
switch v := oe[key].(type) {
case string:
oe[key] = []string{value, preVal.(string)}
case []string:
oe[key] = append(v, preVal.([]string)...)
}
continue
}
oe[key] = value
}
return oe
}

View File

@ -43,11 +43,12 @@ func TestResponseToDSLMap(t *testing.T) {
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."}})
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}})
event := request.responseToDSLMap(req, resp, "one.one.one.one", "one.one.one.one", nil)
require.Len(t, event, 14, "could not get correct number of items in dsl map")
require.Len(t, event, 15, "could not get correct number of items in dsl map")
require.Equal(t, dns.RcodeSuccess, event["rcode"], "could not get correct rcode")
require.ElementsMatch(t, []string{net.ParseIP("1.1.1.1").String(), net.ParseIP("2.2.2.2").String()}, event["a"], "could not get correct a record")
}
func TestDNSOperatorMatch(t *testing.T) {