Skip to content

Commit

Permalink
moved the reverse DNS sweeping into the scripting engine
Browse files Browse the repository at this point in the history
  • Loading branch information
caffix committed Mar 14, 2023
1 parent b749f21 commit 91fd355
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 235 deletions.
109 changes: 108 additions & 1 deletion datasrcs/scripting/dns.go
Expand Up @@ -10,17 +10,29 @@ import (
"fmt"
"net"
"strings"
"sync"
"time"

amassnet "github.com/OWASP/Amass/v3/net"
amassdns "github.com/OWASP/Amass/v3/net/dns"
"github.com/OWASP/Amass/v3/requests"
"github.com/caffix/resolve"
"github.com/miekg/dns"
bf "github.com/tylertreat/BoomFilters"
lua "github.com/yuin/gopher-lua"
"golang.org/x/net/publicsuffix"
)

const (
defaultSweepSize = 250
activeSweepSize = 500
)

var (
sweepLock sync.Mutex
sweepFilter *bf.StableBloomFilter = bf.NewDefaultStableBloomFilter(1000000, 0.01)
)

// Wrapper so that scripts can make DNS queries.
func (s *Script) resolve(L *lua.LState) int {
ctx, err := extractContext(L.CheckUserData(1))
Expand Down Expand Up @@ -139,6 +151,102 @@ func convertType(qtype string) uint16 {
return t
}

func (s *Script) reverseSweep(L *lua.LState) int {
ctx, err := extractContext(L.CheckUserData(1))
if err != nil {
L.Push(lua.LString("failed to obtain the context"))
return 1
}

addr := L.CheckString(2)
if addr == "" {
L.Push(lua.LString("failed to obtain the IP address"))
return 1
}

size := defaultSweepSize
if s.sys.Config().Active {
size = activeSweepSize
}

var cidr *net.IPNet
if asn := s.sys.Cache().AddrSearch(addr); asn != nil {
if _, c, err := net.ParseCIDR(asn.Prefix); err == nil {
cidr = c
}
}

if cidr == nil {
ip := net.ParseIP(addr)
mask := net.CIDRMask(18, 32)
if amassnet.IsIPv6(ip) {
mask = net.CIDRMask(64, 128)
}

cidr = &net.IPNet{
IP: ip.Mask(mask),
Mask: mask,
}
}

var count int
ch := make(chan *resolve.ExtractedAnswer, 10)
for _, ip := range amassnet.CIDRSubset(cidr, addr, size) {
select {
case <-ctx.Done():
L.Push(lua.LString("the context expired"))
return 1
default:
}

sweepLock.Lock()
if a := ip.String(); !sweepFilter.TestAndAdd([]byte(a)) {
count++
go s.getPTR(ctx, a, ch)
}
sweepLock.Unlock()
}

var records []*resolve.ExtractedAnswer
for i := 0; i < count; i++ {
if rr := <-ch; rr != nil {
records = append(records, rr)
}
}

for _, rr := range records {
s.newPTR(ctx, rr)
}
L.Push(lua.LNil)
return 1
}

func (s *Script) getPTR(ctx context.Context, addr string, ch chan *resolve.ExtractedAnswer) {
if reserved, _ := amassnet.IsReservedAddress(addr); reserved {
ch <- nil
return
}

msg := resolve.ReverseMsg(addr)
resp, err := s.dnsQuery(ctx, msg, s.sys.Resolvers(), 10)
if err != nil || resp == nil {
ch <- nil
return
}

resp, err = s.dnsQuery(ctx, msg, s.sys.TrustedResolvers(), 10)
if err != nil || resp == nil {
ch <- nil
return
}

if ans := resolve.ExtractAnswers(resp); len(ans) > 0 {
if records := resolve.AnswersByType(ans, dns.TypePTR); len(records) > 0 {
ch <- records[0]
}
}
}

func (s *Script) zoneWalk(L *lua.LState) int {
ctx, err := extractContext(L.CheckUserData(1))
if err != nil {
Expand Down Expand Up @@ -231,7 +339,6 @@ func (s *Script) wrapZoneTransfer(L *lua.LState) int {
entry.RawSetString("rrdata", lua.LString(rr.Data))
tb.Append(entry)
}

// Zone Transfers can reveal DNS wildcards
if n := amassdns.RemoveAsteriskLabel(req.Name); len(n) < len(req.Name) {
// Signal the wildcard discovery
Expand Down
92 changes: 63 additions & 29 deletions datasrcs/scripting/new.go
Expand Up @@ -7,13 +7,18 @@ package scripting
import (
"context"
"net"
"strings"
"time"

amassnet "github.com/OWASP/Amass/v3/net"
amassdns "github.com/OWASP/Amass/v3/net/dns"
"github.com/OWASP/Amass/v3/net/http"
"github.com/OWASP/Amass/v3/requests"
"github.com/caffix/resolve"
"github.com/miekg/dns"
bf "github.com/tylertreat/BoomFilters"
lua "github.com/yuin/gopher-lua"
"golang.org/x/net/publicsuffix"
)

func (s *Script) genNewName(ctx context.Context, name string) {
Expand All @@ -25,13 +30,12 @@ func (s *Script) newNameWithSrc(ctx context.Context, name, tag, src string) {
select {
case <-ctx.Done():
case <-s.Done():
default:
s.Output() <- &requests.DNSRequest{
Name: name,
Domain: domain,
Tag: tag,
Source: src,
}
case s.Output() <- &requests.DNSRequest{
Name: name,
Domain: domain,
Tag: tag,
Source: src,
}:
}
}
}
Expand Down Expand Up @@ -127,18 +131,50 @@ func (s *Script) internalSendDNSRecords(ctx context.Context, name string, record
select {
case <-ctx.Done():
case <-s.Done():
default:
s.Output() <- &requests.DNSRequest{
Name: name,
Domain: domain,
Records: records,
Tag: s.Description(),
Source: s.String(),
}
case s.Output() <- &requests.DNSRequest{
Name: name,
Domain: domain,
Records: records,
Tag: s.Description(),
Source: s.String(),
}:
}
}
}

func (s *Script) newPTR(ctx context.Context, record *resolve.ExtractedAnswer) {
answer := strings.ToLower(resolve.RemoveLastDot(record.Data))
if amassdns.RemoveAsteriskLabel(answer) != answer {
return
}
// Check that the name discovered is in scope
if d := s.sys.Config().WhichDomain(answer); d == "" {
return
}

ptr := strings.ToLower(resolve.RemoveLastDot(record.Name))
domain, err := publicsuffix.EffectiveTLDPlusOne(ptr)
if err != nil {
return
}

select {
case <-ctx.Done():
case <-s.Done():
case s.Output() <- &requests.DNSRequest{
Name: ptr,
Domain: domain,
Records: []requests.DNSAnswer{{
Name: ptr,
Type: int(dns.TypePTR),
Data: answer,
}},
Tag: s.Description(),
Source: s.String(),
}:
}
}

// Wrapper so that scripts can send discovered IP addresses to Amass.
func (s *Script) newAddr(L *lua.LState) int {
ip := net.ParseIP(L.CheckString(2))
Expand All @@ -155,13 +191,12 @@ func (s *Script) newAddr(L *lua.LState) int {
select {
case <-ctx.Done():
case <-s.Done():
default:
s.Output() <- &requests.AddrRequest{
Address: ip.String(),
Domain: domain,
Tag: s.SourceType,
Source: s.String(),
}
case s.Output() <- &requests.AddrRequest{
Address: ip.String(),
Domain: domain,
Tag: s.SourceType,
Source: s.String(),
}:
}
}
}
Expand Down Expand Up @@ -232,13 +267,12 @@ func (s *Script) associated(L *lua.LState) int {
select {
case <-ctx.Done():
case <-s.Done():
default:
s.Output() <- &requests.WhoisRequest{
Domain: domain,
NewDomains: []string{assoc},
Tag: s.SourceType,
Source: s.String(),
}
case s.Output() <- &requests.WhoisRequest{
Domain: domain,
NewDomains: []string{assoc},
Tag: s.SourceType,
Source: s.String(),
}:
}
}
}
Expand Down
1 change: 1 addition & 0 deletions datasrcs/scripting/script.go
Expand Up @@ -123,6 +123,7 @@ func (s *Script) newLuaState(cfg *config.Config) *lua.LState {
L.SetGlobal("scrape", L.NewFunction(s.scrape))
L.SetGlobal("crawl", L.NewFunction(s.crawl))
L.SetGlobal("resolve", L.NewFunction(s.resolve))
L.SetGlobal("reverse_sweep", L.NewFunction(s.reverseSweep))
L.SetGlobal("zone_walk", L.NewFunction(s.zoneWalk))
L.SetGlobal("zone_transfer", L.NewFunction(s.wrapZoneTransfer))
L.SetGlobal("output_dir", L.NewFunction(s.outputdir))
Expand Down

0 comments on commit 91fd355

Please sign in to comment.