-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathsfp_tldsearch.py
202 lines (159 loc) · 6.35 KB
/
sfp_tldsearch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# Name: sfp_tldsearch
# Purpose: SpiderFoot plug-in for identifying the existence of this target
# on other TLDs.
#
# Author: Steve Micallef <[email protected]>
#
# Created: 31/08/2013
# Copyright: (c) Steve Micallef 2013
# Licence: MIT
# -------------------------------------------------------------------------------
import random
import threading
import time
import dns.resolver
from spiderfoot import SpiderFootEvent, SpiderFootPlugin
class sfp_tldsearch(SpiderFootPlugin):
meta = {
'name': "TLD Searcher",
'summary': "Search all Internet TLDs for domains with the same name as the target (this can be very slow.)",
'flags': ["slow"],
'useCases': ["Footprint"],
'categories': ["DNS"]
}
# Default options
opts = {
'activeonly': False, # Only report domains that have content (try to fetch the page)
'skipwildcards': True,
'_maxthreads': 50
}
# Option descriptions
optdescs = {
'activeonly': "Only report domains that have content (try to fetch the page)?",
"skipwildcards": "Skip TLDs and sub-TLDs that have wildcard DNS.",
"_maxthreads": "Maximum threads"
}
# Internal results tracking
results = None
# Track TLD search results between threads
tldResults = dict()
lock = None
def setup(self, sfc, userOpts=dict()):
self.sf = sfc
self.results = self.tempStorage()
self.__dataSource__ = "DNS"
self.lock = threading.Lock()
for opt in list(userOpts.keys()):
self.opts[opt] = userOpts[opt]
# What events is this module interested in for input
def watchedEvents(self):
return ["INTERNET_NAME"]
# What events this module produces
# This is to support the end user in selecting modules based on events
# produced.
def producedEvents(self):
return ["SIMILARDOMAIN"]
def tryTld(self, target, tld):
resolver = dns.resolver.Resolver()
resolver.timeout = 1
resolver.lifetime = 1
resolver.search = list()
if self.opts.get('_dnsserver', "") != "":
resolver.nameservers = [self.opts['_dnsserver']]
if self.opts['skipwildcards'] and self.sf.checkDnsWildcard(tld):
return
try:
if not self.sf.resolveHost(target) and not self.sf.resolveHost6(target):
with self.lock:
self.tldResults[target] = False
else:
with self.lock:
self.tldResults[target] = True
except Exception:
with self.lock:
self.tldResults[target] = False
def tryTldWrapper(self, tldList, sourceEvent):
self.tldResults = dict()
running = True
t = []
# Spawn threads for scanning
self.info(f"Spawning threads to check TLDs: {tldList}")
for i, pair in enumerate(tldList):
(domain, tld) = pair
tn = 'thread_sfp_tldsearch_' + str(random.SystemRandom().randint(0, 999999999))
t.append(threading.Thread(name=tn, target=self.tryTld, args=(domain, tld,)))
t[i].start()
# Block until all threads are finished
while running:
found = False
for rt in threading.enumerate():
if rt.name.startswith("thread_sfp_tldsearch_"):
found = True
if not found:
running = False
time.sleep(0.1)
for res in self.tldResults:
if self.getTarget().matches(res, includeParents=True, includeChildren=True):
continue
if self.tldResults[res] and res not in self.results:
self.sendEvent(sourceEvent, res)
# Store the result internally and notify listening modules
def sendEvent(self, source, result):
self.info("Found a TLD with the target's name: " + result)
self.results[result] = True
# Inform listening modules
if self.opts['activeonly']:
if self.checkForStop():
return
pageContent = self.sf.fetchUrl('http://' + result,
timeout=self.opts['_fetchtimeout'],
useragent=self.opts['_useragent'],
noLog=True,
verify=False)
if pageContent['content'] is not None:
evt = SpiderFootEvent("SIMILARDOMAIN", result, self.__name__, source)
self.notifyListeners(evt)
else:
evt = SpiderFootEvent("SIMILARDOMAIN", result, self.__name__, source)
self.notifyListeners(evt)
# Search for similar sounding domains
def handleEvent(self, event):
eventData = event.data
if eventData in self.results:
return
self.results[eventData] = True
keyword = self.sf.domainKeyword(eventData, self.opts['_internettlds'])
if not keyword:
self.error(f"Failed to extract keyword from {eventData}")
return
self.debug(f"Keyword extracted from {eventData}: {keyword}")
if keyword in self.results:
return
self.results[keyword] = True
# Look through all TLDs for the existence of this target keyword
targetList = list()
for tld in self.opts['_internettlds']:
if not isinstance(tld, str):
tld = str(tld.strip(), errors='ignore')
else:
tld = tld.strip()
if tld.startswith("//") or len(tld) == 0:
continue
if tld.startswith("!") or tld.startswith("*") or tld.startswith(".."):
continue
if tld.endswith(".arpa"):
continue
tryDomain = keyword + "." + tld
if self.checkForStop():
return
if len(targetList) <= self.opts['_maxthreads']:
targetList.append([tryDomain, tld])
else:
self.tryTldWrapper(targetList, event)
targetList = list()
# Scan whatever may be left over.
if len(targetList) > 0:
self.tryTldWrapper(targetList, event)
# End of sfp_tldsearch class