2020-04-22 20:45:02 +00:00
|
|
|
package requests
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/miekg/dns"
|
2020-07-01 10:47:24 +00:00
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/extractors"
|
|
|
|
"github.com/projectdiscovery/nuclei/v2/pkg/matchers"
|
2020-04-22 20:45:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// DNSRequest contains a request to be made from a template
|
|
|
|
type DNSRequest struct {
|
|
|
|
Recursion bool `yaml:"recursion"`
|
|
|
|
// Path contains the path/s for the request
|
|
|
|
Name string `yaml:"name"`
|
|
|
|
Type string `yaml:"type"`
|
|
|
|
Class string `yaml:"class"`
|
|
|
|
Retries int `yaml:"retries"`
|
2020-04-28 21:03:08 +00:00
|
|
|
// Raw contains a raw request
|
|
|
|
Raw string `yaml:"raw,omitempty"`
|
2020-04-22 20:45:02 +00:00
|
|
|
|
|
|
|
// Matchers contains the detection mechanism for the request to identify
|
|
|
|
// whether the request was successful
|
|
|
|
Matchers []*matchers.Matcher `yaml:"matchers,omitempty"`
|
2020-04-26 01:03:59 +00:00
|
|
|
// matchersCondition is internal condition for the matchers.
|
|
|
|
matchersCondition matchers.ConditionType
|
|
|
|
// MatchersCondition is the condition of the matchers
|
|
|
|
// whether to use AND or OR. Default is OR.
|
|
|
|
MatchersCondition string `yaml:"matchers-condition,omitempty"`
|
2020-04-22 20:45:02 +00:00
|
|
|
// Extractors contains the extraction mechanism for the request to identify
|
|
|
|
// and extract parts of the response.
|
|
|
|
Extractors []*extractors.Extractor `yaml:"extractors,omitempty"`
|
|
|
|
}
|
|
|
|
|
2020-04-26 01:03:59 +00:00
|
|
|
// GetMatchersCondition returns the condition for the matcher
|
|
|
|
func (r *DNSRequest) GetMatchersCondition() matchers.ConditionType {
|
|
|
|
return r.matchersCondition
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetMatchersCondition sets the condition for the matcher
|
|
|
|
func (r *DNSRequest) SetMatchersCondition(condition matchers.ConditionType) {
|
|
|
|
r.matchersCondition = condition
|
|
|
|
}
|
|
|
|
|
2020-07-26 14:36:01 +00:00
|
|
|
// Returns the total number of requests the YAML rule will perform
|
|
|
|
func (r *DNSRequest) GetRequestCount() int64 {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2020-04-22 20:45:02 +00:00
|
|
|
// MakeDNSRequest creates a *dns.Request from a request template
|
|
|
|
func (r *DNSRequest) MakeDNSRequest(domain string) (*dns.Msg, error) {
|
|
|
|
domain = dns.Fqdn(domain)
|
|
|
|
|
|
|
|
// Build a request on the specified URL
|
|
|
|
req := new(dns.Msg)
|
|
|
|
req.Id = dns.Id()
|
|
|
|
req.RecursionDesired = r.Recursion
|
|
|
|
|
|
|
|
var q dns.Question
|
|
|
|
|
2020-04-30 15:39:33 +00:00
|
|
|
replacer := newReplacer(map[string]interface{}{"FQDN": domain})
|
|
|
|
|
|
|
|
q.Name = dns.Fqdn(replacer.Replace(r.Name))
|
2020-04-26 00:20:33 +00:00
|
|
|
q.Qclass = toQClass(r.Class)
|
|
|
|
q.Qtype = toQType(r.Type)
|
2020-04-22 20:45:02 +00:00
|
|
|
|
|
|
|
req.Question = append(req.Question, q)
|
|
|
|
|
|
|
|
return req, nil
|
|
|
|
}
|
|
|
|
|
2020-04-26 00:20:33 +00:00
|
|
|
func toQType(ttype string) (rtype uint16) {
|
2020-04-22 20:45:02 +00:00
|
|
|
ttype = strings.TrimSpace(strings.ToUpper(ttype))
|
|
|
|
|
|
|
|
switch ttype {
|
|
|
|
case "A":
|
|
|
|
rtype = dns.TypeA
|
|
|
|
case "NS":
|
|
|
|
rtype = dns.TypeNS
|
|
|
|
case "CNAME":
|
|
|
|
rtype = dns.TypeCNAME
|
|
|
|
case "SOA":
|
|
|
|
rtype = dns.TypeSOA
|
|
|
|
case "PTR":
|
|
|
|
rtype = dns.TypePTR
|
|
|
|
case "MX":
|
|
|
|
rtype = dns.TypeMX
|
|
|
|
case "TXT":
|
|
|
|
rtype = dns.TypeTXT
|
|
|
|
case "AAAA":
|
|
|
|
rtype = dns.TypeAAAA
|
|
|
|
default:
|
2020-04-26 00:20:33 +00:00
|
|
|
rtype = dns.TypeA
|
2020-04-22 20:45:02 +00:00
|
|
|
}
|
2020-08-25 21:24:31 +00:00
|
|
|
|
2020-04-22 20:45:02 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-26 00:20:33 +00:00
|
|
|
func toQClass(tclass string) (rclass uint16) {
|
2020-04-22 20:45:02 +00:00
|
|
|
tclass = strings.TrimSpace(strings.ToUpper(tclass))
|
|
|
|
|
|
|
|
switch tclass {
|
|
|
|
case "INET":
|
|
|
|
rclass = dns.ClassINET
|
|
|
|
case "CSNET":
|
|
|
|
rclass = dns.ClassCSNET
|
|
|
|
case "CHAOS":
|
|
|
|
rclass = dns.ClassCHAOS
|
|
|
|
case "HESIOD":
|
|
|
|
rclass = dns.ClassHESIOD
|
|
|
|
case "NONE":
|
|
|
|
rclass = dns.ClassNONE
|
|
|
|
case "ANY":
|
|
|
|
rclass = dns.ClassANY
|
|
|
|
default:
|
2020-04-26 00:20:33 +00:00
|
|
|
// Use INET by default.
|
|
|
|
rclass = dns.ClassINET
|
2020-04-22 20:45:02 +00:00
|
|
|
}
|
2020-08-25 21:24:31 +00:00
|
|
|
|
2020-04-22 20:45:02 +00:00
|
|
|
return
|
|
|
|
}
|