diff --git a/cli/cmd/dns.go b/cli/cmd/dns.go index 1d431f40..c37fb0c1 100644 --- a/cli/cmd/dns.go +++ b/cli/cmd/dns.go @@ -76,6 +76,11 @@ func parseDNSOptions() (*libgobuster.Options, *gobusterdns.OptionsDNS, error) { return nil, nil, fmt.Errorf("invalid value for resolver: %w", err) } + pluginOpts.NoFQDN, err = cmdDNS.Flags().GetBool("no-fqdn") + if err != nil { + return nil, nil, fmt.Errorf("invalid value for no-fqdn: %w", err) + } + if pluginOpts.Resolver != "" && runtime.GOOS == "windows" { return nil, nil, fmt.Errorf("currently can not set custom dns resolver on windows. See https://golang.org/pkg/net/#hdr-Name_Resolution") } @@ -96,6 +101,7 @@ func init() { cmdDNS.Flags().BoolP("show-cname", "c", false, "Show CNAME records (cannot be used with '-i' option)") cmdDNS.Flags().DurationP("timeout", "", time.Second, "DNS resolver timeout") cmdDNS.Flags().BoolP("wildcard", "", false, "Force continued operation when wildcard found") + cmdDNS.Flags().BoolP("no-fqdn", "", false, "Do not automatically add a trailing dot to the domain, so the resolver uses the DNS search domain") cmdDNS.Flags().StringP("resolver", "r", "", "Use custom DNS server (format server.com or server.com:port)") if err := cmdDNS.MarkFlagRequired("domain"); err != nil { log.Fatalf("error on marking flag as required: %v", err) diff --git a/gobusterdns/gobusterdns.go b/gobusterdns/gobusterdns.go index 6d253dda..c8ce106a 100644 --- a/gobusterdns/gobusterdns.go +++ b/gobusterdns/gobusterdns.go @@ -111,6 +111,9 @@ func (d *GobusterDNS) PreRun(ctx context.Context, progress *libgobuster.Progress // ProcessWord is the process implementation of gobusterdns func (d *GobusterDNS) ProcessWord(ctx context.Context, word string, progress *libgobuster.Progress) error { subdomain := fmt.Sprintf("%s.%s", word, d.options.Domain) + if !d.options.NoFQDN && !strings.HasSuffix(subdomain, ".") { + subdomain += "." + } ips, err := d.dnsLookup(ctx, subdomain) if err == nil { if !d.isWildcard || !d.wildcardIps.ContainsAny(ips) { @@ -119,6 +122,7 @@ func (d *GobusterDNS) ProcessWord(ctx context.Context, word string, progress *li Found: true, ShowIPs: d.options.ShowIPs, ShowCNAME: d.options.ShowCNAME, + NoFQDN: d.options.NoFQDN, } if d.options.ShowIPs { result.IPs = ips diff --git a/gobusterdns/options.go b/gobusterdns/options.go index b5b276e4..1c6cfd1d 100644 --- a/gobusterdns/options.go +++ b/gobusterdns/options.go @@ -11,6 +11,7 @@ type OptionsDNS struct { ShowCNAME bool WildcardForced bool Resolver string + NoFQDN bool Timeout time.Duration } diff --git a/gobusterdns/result.go b/gobusterdns/result.go index b93501d6..b55a5ed4 100644 --- a/gobusterdns/result.go +++ b/gobusterdns/result.go @@ -19,6 +19,7 @@ type Result struct { ShowCNAME bool Found bool Subdomain string + NoFQDN bool IPs []netip.Addr CNAME string } @@ -29,6 +30,9 @@ func (r Result) ResultToString() (string, error) { c := green + if !r.NoFQDN { + r.Subdomain = strings.TrimSuffix(r.Subdomain, ".") + } if r.Found { c(buf, "Found: ") } else {