From f4de409ee9987437ba4e82a4d1a9f7ca8ebc6421 Mon Sep 17 00:00:00 2001 From: 5amu Date: Thu, 7 Jul 2022 00:03:34 +0200 Subject: [PATCH] soainfo refactor --- internal/dnschecks/soainfo.go | 112 +++++++++++++++------------------- 1 file changed, 49 insertions(+), 63 deletions(-) diff --git a/internal/dnschecks/soainfo.go b/internal/dnschecks/soainfo.go index b3700b7..8cc4bbe 100644 --- a/internal/dnschecks/soainfo.go +++ b/internal/dnschecks/soainfo.go @@ -3,8 +3,6 @@ package dnschecks import ( "fmt" "net" - "regexp" - "strings" "time" "github.com/5amu/dnshunter/internal/common" @@ -41,7 +39,7 @@ func (c *SOACheck) Start(domain string, nameservers *common.Nameservers) error { var parsed string for _, soa := range r.Answer { - isVuln, parsed = parseSOA(soa.String()) + isVuln, parsed = parseSOA(soa.(*dns.SOA)) } c.output = &output.CheckOutput{ @@ -69,70 +67,58 @@ func (c *SOACheck) Results() *output.CheckOutput { return c.output } -func parseSOA(soa string) (isVuln bool, message string) { - message += "\n" +func parseSOA(soa *dns.SOA) (isVuln bool, message string) { + message += "\nChecking if SOA record follows RIPE-203 standard\n" + message += "more info at https://www.ripe.net/publications/docs/ripe-203\n\n" + message += fmt.Sprintf("Zone name: %v\n", soa.Ns) + message += fmt.Sprintf("Start of Authority: %v\n", soa.Mbox) + message += parseSerial(fmt.Sprint(soa.Serial), &isVuln) + message += parseRefresh(fmt.Sprint(soa.Refresh), &isVuln) + message += parseRetry(fmt.Sprint(soa.Retry), &isVuln) + message += parseExpire(fmt.Sprint(soa.Expire), &isVuln) + message += fmt.Sprintf("TTL: %v\n", soa.Hdr.Ttl) + return +} - splitted := strings.Split(soa, "SOA") - if len(splitted) < 2 { - message += "Invalid answer" - return true, message +func parseSerial(serial string, isVuln *bool) string { + serialDate, _ := time.Parse("%Y%m%d", string(serial)[:4]) + dummyLower, _ := time.Parse("%s", "0") + dummyUpper, _ := time.Parse("%s", fmt.Sprintf("%v", time.Now().Unix())) + if serialDate.After(dummyUpper) || serialDate.Before(dummyLower) { + *isVuln = true + return common.Warn(fmt.Sprintf("Serial number: %v - should follow standards (RIPE-203)\n", serial)) + } else { + return fmt.Sprintf("Serial number: %v\n", serial) } +} - // get answer section and remove whitespaces - s := regexp.MustCompile(`\s+`) - record := string(s.ReplaceAll([]byte(splitted[1]), []byte(" "))) +func parseRefresh(refresh string, isVuln *bool) string { + r, _ := time.ParseDuration(fmt.Sprintf("%vs", refresh)) + if r < (24 * time.Hour) { + *isVuln = true + return common.Warn(fmt.Sprintf("Refresh: %v - should follow standards (RIPE-203)\n", refresh)) + } else { + return fmt.Sprintf("Refresh: %v\n", refresh) + } +} - message += "Checking if SOA record follows RIPE-203 standard\n" - message += "more info at https://www.ripe.net/publications/docs/ripe-203\n\n" +func parseRetry(retry string, isVuln *bool) string { + r, _ := time.ParseDuration(fmt.Sprintf("%vs", retry)) + if r < (2 * time.Hour) { + *isVuln = true + return common.Warn(fmt.Sprintf("Retry: %v - should follow standards (RIPE-203)\n", retry)) + } else { + return fmt.Sprintf("Retry: %v\n", retry) + } +} - for i, part := range strings.Split(record, " ") { - switch i { - case SOAName: - message += fmt.Sprintf("Zone name: %v\n", part) - case SOARecord: - message += fmt.Sprintf("Start of Authority: %v\n", part) - case SOASerial: - serialDate, _ := time.Parse("%Y%m%d", part[:len(part)-2]) - dummyLower, _ := time.Parse("%s", "0") - dummyUpper, _ := time.Parse("%s", fmt.Sprintf("%v", time.Now().Unix())) - - if serialDate.After(dummyUpper) || serialDate.Before(dummyLower) { - message += common.Warn(fmt.Sprintf("Serial number: %v - should follow standards (RIPE-203)\n", part)) - isVuln = true - } else { - message += fmt.Sprintf("Serial number: %v\n", part) - } - case SOARefresh: - refresh, _ := time.ParseDuration(fmt.Sprintf("%vs", part)) - - if refresh < (24 * time.Hour) { - message += common.Warn(fmt.Sprintf("Refresh: %v - should follow standards (RIPE-203)\n", part)) - isVuln = true - } else { - message += fmt.Sprintf("Refresh: %v\n", part) - } - case SOARetry: - retry, _ := time.ParseDuration(fmt.Sprintf("%vs", part)) - - if retry < (2 * time.Hour) { - message += common.Warn(fmt.Sprintf("Retry: %v - should follow standards (RIPE-203)\n", part)) - isVuln = true - } else { - message += fmt.Sprintf("Retry: %v\n", part) - } - case SOAExpire: - expire, _ := time.ParseDuration(fmt.Sprintf("%vs", part)) - - if expire < (1000 * time.Hour) { - message += common.Warn(fmt.Sprintf("Expire: %v - should follow standards (RIPE-203)\n", part)) - isVuln = true - } else { - message += fmt.Sprintf("Expire: %v\n", part) - } - case SOATTL: - message += fmt.Sprintf("TTL: %v\n", part) - } +func parseExpire(expire string, isVuln *bool) string { + e, _ := time.ParseDuration(fmt.Sprintf("%vs", expire)) + + if e < (1000 * time.Hour) { + *isVuln = true + return common.Warn(fmt.Sprintf("Expire: %v - should follow standards (RIPE-203)\n", expire)) + } else { + return fmt.Sprintf("Expire: %v\n", expire) } - message += "\n" - return }