0 | 0 |
#!/usr/bin/env python3
|
1 | 1 |
|
2 | 2 |
import json
|
|
3 |
import aiohttp
|
3 | 4 |
import asyncio
|
4 | |
import requests
|
5 | 5 |
import psycopg2
|
6 | 6 |
|
7 | 7 |
R = '\033[31m' # red
|
|
12 | 12 |
|
13 | 13 |
found = []
|
14 | 14 |
|
15 | |
async def buffover(hostname, tout):
|
|
15 |
async def buffover(hostname, session):
|
16 | 16 |
global found
|
17 | 17 |
print(Y + '[!]' + C + ' Requesting ' + G + 'BuffOver' + W)
|
18 | 18 |
url = 'https://dns.bufferover.run/dns'
|
19 | |
data = {
|
20 | |
'q': '.{}'.format(hostname)
|
21 | |
}
|
22 | |
try:
|
23 | |
r = requests.get(url, params=data, timeout=tout)
|
24 | |
sc = r.status_code
|
25 | |
if sc == 200:
|
26 | |
output = r.content.decode()
|
27 | |
json_out = json.loads(output)
|
28 | |
subds = json_out['FDNS_A']
|
29 | |
if subds == None:
|
30 | |
pass
|
31 | |
else:
|
32 | |
for subd in subds:
|
33 | |
subd = subd.split(',')
|
34 | |
for sub in subd:
|
35 | |
found.append(sub)
|
36 | |
else:
|
37 | |
print(R + '[-]' + C + ' BuffOver Status : ' + W + str(sc))
|
|
19 |
bo_params = {
|
|
20 |
'q': '.{}'.format(hostname)
|
|
21 |
}
|
|
22 |
try:
|
|
23 |
async with session.get(url, params=bo_params) as resp:
|
|
24 |
sc = resp.status
|
|
25 |
if sc == 200:
|
|
26 |
output = await resp.text()
|
|
27 |
json_out = json.loads(output)
|
|
28 |
subds = json_out['FDNS_A']
|
|
29 |
if subds == None:
|
|
30 |
pass
|
|
31 |
else:
|
|
32 |
for subd in subds:
|
|
33 |
subd = subd.split(',')
|
|
34 |
for sub in subd:
|
|
35 |
found.append(sub)
|
|
36 |
else:
|
|
37 |
print(R + '[-]' + C + ' BuffOver Status : ' + W + str(sc))
|
38 | 38 |
except Exception as e:
|
39 | 39 |
print(R + '[-]' + C + ' BuffOver Exception : ' + W + str(e))
|
40 | 40 |
|
|
55 | 55 |
except Exception as e:
|
56 | 56 |
print(R + '[-]' + C + ' crtsh Exception : ' + W + str(e))
|
57 | 57 |
|
58 | |
async def thcrowd(hostname, tout):
|
59 | |
global found
|
60 | |
print(Y + '[!]' + C + ' Requesting ' + G + 'ThreadCrowd' + W)
|
|
58 |
async def thcrowd(hostname, session):
|
|
59 |
global found
|
|
60 |
print(Y + '[!]' + C + ' Requesting ' + G + 'ThreatCrowd' + W)
|
61 | 61 |
url = 'https://www.threatcrowd.org/searchApi/v2/domain/report/'
|
62 | |
data = {
|
63 | |
'domain': hostname
|
64 | |
}
|
65 | |
try:
|
66 | |
r = requests.get(url, params=data, timeout=tout)
|
67 | |
sc = r.status_code
|
68 | |
if sc == 200:
|
69 | |
output = r.content.decode()
|
70 | |
json_out = json.loads(output)
|
71 | |
if json_out['response_code'] == '0':
|
72 | |
pass
|
73 | |
else:
|
74 | |
subd = json_out['subdomains']
|
75 | |
found.extend(subd)
|
76 | |
else:
|
77 | |
print(R + '[-]' + C + ' ThreatCrowd Status : ' + W + str(sc))
|
|
62 |
thc_params = {
|
|
63 |
'domain': hostname
|
|
64 |
}
|
|
65 |
try:
|
|
66 |
async with session.get(url, params=thc_params) as resp:
|
|
67 |
sc = resp.status
|
|
68 |
if sc == 200:
|
|
69 |
output = await resp.text()
|
|
70 |
json_out = json.loads(output)
|
|
71 |
if json_out['response_code'] == '0':
|
|
72 |
pass
|
|
73 |
else:
|
|
74 |
subd = json_out['subdomains']
|
|
75 |
found.extend(subd)
|
|
76 |
else:
|
|
77 |
print(R + '[-]' + C + ' ThreatCrowd Status : ' + W + str(sc))
|
78 | 78 |
except Exception as e:
|
79 | 79 |
print(R + '[-]' + C + ' ThreatCrowd Exception : ' + W + str(e))
|
80 | 80 |
|
81 | |
async def anubisdb(hostname, tout):
|
|
81 |
async def anubisdb(hostname, session):
|
82 | 82 |
global found
|
83 | 83 |
print(Y + '[!]' + C + ' Requesting ' + G + 'AnubisDB' + W)
|
84 | 84 |
url = 'https://jldc.me/anubis/subdomains/{}'.format(hostname)
|
85 | 85 |
try:
|
86 | |
r = requests.get(url, timeout=tout)
|
87 | |
sc = r.status_code
|
88 | |
if sc == 200:
|
89 | |
output = r.content.decode()
|
90 | |
json_out = json.loads(output)
|
91 | |
found.extend(json_out)
|
92 | |
elif sc == 300:
|
93 | |
pass
|
94 | |
else:
|
95 | |
print(R + '[-]' + C + ' AnubisDB Status : ' + W + str(sc))
|
|
86 |
async with session.get(url) as resp:
|
|
87 |
sc = resp.status
|
|
88 |
if sc == 200:
|
|
89 |
output = await resp.text()
|
|
90 |
json_out = json.loads(output)
|
|
91 |
found.extend(json_out)
|
|
92 |
elif sc == 300:
|
|
93 |
pass
|
|
94 |
else:
|
|
95 |
print(R + '[-]' + C + ' AnubisDB Status : ' + W + str(sc))
|
96 | 96 |
except Exception as e:
|
97 | 97 |
print(R + '[-]' + C + 'AnubisDB Exception : ' + W + str(e))
|
98 | 98 |
|
99 | |
async def thminer(hostname, tout):
|
|
99 |
async def thminer(hostname, session):
|
100 | 100 |
global found
|
101 | 101 |
print(Y + '[!]' + C + ' Requesting ' + G + 'ThreatMiner' + W)
|
102 | |
url = 'https://api.threatminer.org/v2/domain.php?q=instagram.com&rt=5'
|
103 | |
data = {
|
104 | |
'q': hostname,
|
105 | |
'rt': '5'
|
106 | |
}
|
107 | |
try:
|
108 | |
r = requests.get(url, params=data, timeout=tout)
|
109 | |
sc = r.status_code
|
110 | |
if sc == 200:
|
111 | |
output = r.content.decode()
|
112 | |
json_out = json.loads(output)
|
113 | |
subd = json_out['results']
|
114 | |
found.extend(subd)
|
115 | |
else:
|
116 | |
print(R + '[-]' + C + ' ThreatMiner Status : ' + W + str(sc))
|
|
102 |
url = 'https://api.threatminer.org/v2/domain.php'
|
|
103 |
thm_params = {
|
|
104 |
'q': hostname,
|
|
105 |
'rt': '5'
|
|
106 |
}
|
|
107 |
try:
|
|
108 |
async with session.get(url, params=thm_params) as resp:
|
|
109 |
sc = resp.status
|
|
110 |
if sc == 200:
|
|
111 |
output = await resp.text()
|
|
112 |
json_out = json.loads(output)
|
|
113 |
subd = json_out['results']
|
|
114 |
found.extend(subd)
|
|
115 |
else:
|
|
116 |
print(R + '[-]' + C + ' ThreatMiner Status : ' + W + str(sc))
|
117 | 117 |
except Exception as e:
|
118 | 118 |
print(R + '[-]' + C + ' ThreatMiner Exception : ' + W + str(e))
|
119 | 119 |
|
120 | |
async def fb_cert(hostname, tout):
|
121 | |
global found
|
122 | |
with open('conf/keys.json', 'r') as keyfile:
|
|
120 |
async def fb_cert(hostname, conf_path, session):
|
|
121 |
global found
|
|
122 |
with open('{}/keys.json'.format(conf_path), 'r') as keyfile:
|
123 | 123 |
json_read = keyfile.read()
|
124 | 124 |
|
125 | 125 |
json_load = json.loads(json_read)
|
|
128 | 128 |
if fb_key != None:
|
129 | 129 |
print(Y + '[!]' + C + ' Requesting ' + G + 'Facebook' + W)
|
130 | 130 |
url = 'https://graph.facebook.com/certificates'
|
131 | |
data = {
|
|
131 |
fb_params = {
|
132 | 132 |
'query': hostname,
|
133 | 133 |
'fields': 'domains',
|
134 | 134 |
'access_token': fb_key
|
135 | 135 |
}
|
136 | |
|
137 | |
r = requests.get(url, params=data, timeout=tout)
|
138 | |
json_data = r.text
|
139 | |
json_read = json.loads(json_data)
|
140 | |
domains = json_read['data']
|
141 | |
|
142 | |
for i in range (0, len(domains)):
|
143 | |
found.extend(json_read['data'][i]['domains'])
|
|
136 |
try:
|
|
137 |
async with session.get(url, params=fb_params) as resp:
|
|
138 |
sc = resp.status
|
|
139 |
if sc == 200:
|
|
140 |
json_data = await resp.text()
|
|
141 |
json_read = json.loads(json_data)
|
|
142 |
domains = json_read['data']
|
|
143 |
for i in range (0, len(domains)):
|
|
144 |
found.extend(json_read['data'][i]['domains'])
|
|
145 |
else:
|
|
146 |
print(R + '[-]' + C + ' Facebook Status : ' + W + str(sc))
|
|
147 |
except Exception as e:
|
|
148 |
print(R + '[-]' + C + ' Facebook Exception : ' + W + str(e))
|
144 | 149 |
else:
|
145 | 150 |
pass
|
146 | 151 |
|
147 | |
async def query(hostname, tout):
|
148 | |
await asyncio.gather(
|
149 | |
buffover(hostname, tout),
|
150 | |
thcrowd(hostname, tout),
|
151 | |
crtsh(hostname),
|
152 | |
anubisdb(hostname, tout),
|
153 | |
thminer(hostname, tout),
|
154 | |
fb_cert(hostname, tout)
|
|
152 |
async def virust(hostname, conf_path, session):
|
|
153 |
global found
|
|
154 |
with open('{}/keys.json'.format(conf_path), 'r') as keyfile:
|
|
155 |
json_read = keyfile.read()
|
|
156 |
|
|
157 |
json_load = json.loads(json_read)
|
|
158 |
vt_key = json_load['virustotal']
|
|
159 |
|
|
160 |
if vt_key != None:
|
|
161 |
print(Y + '[!]' + C + ' Requesting ' + G + 'VirusTotal' + W)
|
|
162 |
url = 'https://www.virustotal.com/api/v3/domains/{}/subdomains'.format(hostname)
|
|
163 |
vt_headers = {
|
|
164 |
'x-apikey': vt_key
|
|
165 |
}
|
|
166 |
try:
|
|
167 |
async with session.get(url, headers=vt_headers) as resp:
|
|
168 |
sc = resp.status
|
|
169 |
if sc == 200:
|
|
170 |
json_data = await resp.text()
|
|
171 |
json_read = json.loads(json_data)
|
|
172 |
domains = json_read['data']
|
|
173 |
tmp_list = []
|
|
174 |
for i in range (0, len(domains)):
|
|
175 |
tmp_list.append(domains[i]['id'])
|
|
176 |
found.extend(tmp_list)
|
|
177 |
else:
|
|
178 |
print(R + '[-]' + C + ' VirusTotal Status : ' + W + str(sc))
|
|
179 |
except Exception as e:
|
|
180 |
print(R + '[-]' + C + ' VirusTotal Exception : ' + W + str(e))
|
|
181 |
else:
|
|
182 |
pass
|
|
183 |
|
|
184 |
async def certspot(hostname, session):
|
|
185 |
global found
|
|
186 |
|
|
187 |
print(Y + '[!]' + C + ' Requesting ' + G + 'CertSpotter' + W)
|
|
188 |
url = 'https://api.certspotter.com/v1/issuances'
|
|
189 |
cs_params = {
|
|
190 |
'domain': hostname,
|
|
191 |
'expand': 'dns_names',
|
|
192 |
'include_subdomains': 'true'
|
|
193 |
}
|
|
194 |
|
|
195 |
try:
|
|
196 |
async with session.get(url, params=cs_params) as resp:
|
|
197 |
sc = resp.status
|
|
198 |
if sc == 200:
|
|
199 |
json_data = await resp.text()
|
|
200 |
json_read = json.loads(json_data)
|
|
201 |
for i in range (0, len(json_read)):
|
|
202 |
domains = json_read[i]['dns_names']
|
|
203 |
found.extend(domains)
|
|
204 |
else:
|
|
205 |
print(R + '[-]' + C + ' CertSpotter Status : ' + W + str(sc))
|
|
206 |
except Exception as e:
|
|
207 |
print(R + '[-]' + C + ' CertSpotter Exception : ' + W + str(e))
|
|
208 |
|
|
209 |
async def query(hostname, tout, conf_path):
|
|
210 |
timeout = aiohttp.ClientTimeout(total=tout)
|
|
211 |
async with aiohttp.ClientSession(timeout=timeout) as session:
|
|
212 |
await asyncio.gather(
|
|
213 |
buffover(hostname, session),
|
|
214 |
thcrowd(hostname, session),
|
|
215 |
anubisdb(hostname, session),
|
|
216 |
thminer(hostname, session),
|
|
217 |
fb_cert(hostname, conf_path, session),
|
|
218 |
virust(hostname, conf_path, session),
|
|
219 |
certspot(hostname, session),
|
|
220 |
crtsh(hostname)
|
155 | 221 |
)
|
156 | |
|
157 | |
def subdomains(hostname, tout, output, data):
|
|
222 |
await session.close()
|
|
223 |
|
|
224 |
def subdomains(hostname, tout, output, data, conf_path):
|
158 | 225 |
global found
|
159 | 226 |
result = {}
|
160 | 227 |
|
|
162 | 229 |
|
163 | 230 |
loop = asyncio.new_event_loop()
|
164 | 231 |
asyncio.set_event_loop(loop)
|
165 | |
loop.run_until_complete(query(hostname, tout))
|
|
232 |
loop.run_until_complete(query(hostname, tout, conf_path))
|
166 | 233 |
loop.close()
|
167 | 234 |
|
|
235 |
from urllib.parse import urlparse
|
|
236 |
found = [item for item in found if item.endswith(hostname)]
|
|
237 |
valid = r"^[A-Za-z0-9._~()'!*:@,;+?-]*$"
|
|
238 |
import re
|
|
239 |
found = [item for item in found if re.match(valid, item)]
|
168 | 240 |
found = set(found)
|
169 | 241 |
total = len(found)
|
170 | 242 |
|