Last active
August 10, 2021 17:17
-
-
Save daddycocoaman/3438d33b511ef2dbe1eb38cd66c782e6 to your computer and use it in GitHub Desktop.
Async CNAME Enumeration (WIP)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import aiodns | |
import aiofiles | |
import aiohttp | |
from colorama import Fore | |
from dataclasses import field, dataclass | |
from pycares import ares_query_cname_result | |
from concurrent.futures import ThreadPoolExecutor | |
import sys | |
import re | |
@dataclass | |
class DomainEntry: | |
name: str | |
found: bool = True | |
initresult: ares_query_cname_result = field(repr=False, default=None) | |
cnames: dict = field(default_factory=dict) | |
def __str__(self): | |
namecolor = Fore.GREEN if self.found else Fore.RED | |
cnamelist = "".join([f'\n\t{v}{k}' for k,v in self.cnames.items()]) | |
return f'{namecolor}{self.name}:{cnamelist}' | |
PROVIDERS = { | |
'S3': | |
{ | |
'httpvalue': '<Code>NoSuchBucket</Code>|<li>Code: NoSuchBucket</li>', | |
'regex': [ | |
re.compile("^[a-z0-9\.\-]{0,63}\.?s3.amazonaws\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,63}\.s3-website[\.-](eu|ap|us|ca|sa|cn)-\w{2,14}-\d{1,2}\.amazonaws.com(\.cn)?$"), | |
re.compile("^[a-z0-9\.\-]{3,63}\.s3[\.-](eu|ap|us|ca|sa)-\w{2,14}-\d{1,2}\.amazonaws.com$"), | |
re.compile("^[a-z0-9\.\-]{3,63}\.s3.dualstack\.(eu|ap|us|ca|sa)-\w{2,14}-\d{1,2}\.amazonaws.com$") | |
] | |
}, | |
'Azure': | |
{ | |
'regex': [ | |
re.compile("^[a-z0-9\.\-]{3,90}\.azure-api\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurecontainer\.io$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurecr\.io$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azuredatalakestore\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azureedge\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurefd\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurehdinsight\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurewebsites.windows.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.azurewebsites\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.cloudapp\.azure\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.cloudapp\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.core\.windows\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.database.windows\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.documents\.azure\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.mail\.protection\.outlook\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.onmicrosoft\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.redis.cache.windows\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.search.windows\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.servicebus.windows\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.sharepoint\.com$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.trafficmanager\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.vault\.azure\.net$"), | |
re.compile("^[a-z0-9\.\-]{3,90}\.visualstudio\.com$") | |
] | |
} | |
} | |
loop = asyncio.get_event_loop() | |
resolver = aiodns.DNSResolver(loop=loop, nameservers=['8.8.8.8']) | |
resolved = {} | |
async def checkProvider(domain): | |
for prov, values in PROVIDERS.items(): | |
if any(reg.match(domain) for reg in values['regex']): | |
if prov == "S3": | |
async with aiohttp.ClientSession() as sess: | |
async with sess.get(domain) as resp: | |
if values['httpvalue'] in resp: | |
return Fore.MAGENTA | |
else: | |
return Fore.GREEN | |
elif prov == "Azure": | |
return Fore.LIGHTBLUE_EX | |
return False | |
async def checkNotFound(domain, q): | |
try: | |
while hasattr(q, "cname"): | |
resolved[domain].append(q.cname) | |
try: | |
q = await query(q.cname, "CNAME") | |
resolved[domain].append(q.cname) | |
except: | |
break | |
cnames = "\n\t".join(resolved[domain]) | |
print(f"{Fore.RED}{domain}\n\t{Fore.YELLOW}{cnames}") | |
except: | |
pass | |
finally: | |
return None | |
async def query(name, query_type): | |
return await resolver.query(name, query_type) | |
async def main(): | |
with ThreadPoolExecutor() as io_pool_exc: | |
async with aiofiles.open(sys.argv[1], executor=io_pool_exc) as names: | |
async for domain in names: | |
domain = domain.rstrip("\n") | |
entry = DomainEntry(domain) | |
try: | |
entry.initresult = await query(domain, "CNAME") | |
except aiodns.error.DNSError as e: | |
if e.args[0] == 1: | |
continue | |
elif e.args[0] == 4: | |
entry.found = False | |
try: | |
if entry.initresult: | |
q = entry.initresult | |
while hasattr(q, "cname"): | |
#print (Fore.RESET, domain, q.cname) | |
entry.cnames[q.cname] = Fore.WHITE | |
q = await query(q.cname, "CNAME") | |
except aiodns.error.DNSError as e: | |
pass | |
for cname in entry.cnames: | |
prov = await checkProvider(cname) | |
if prov: | |
entry.cnames[cname] = prov | |
#Uncomment this line to see all entries output | |
#print(entry) | |
if not entry.found: | |
print(entry) | |
io_pool_exc.shutdown() | |
if __name__ == "__main__": | |
loop.run_until_complete(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
aiodns==2.0.0 | |
aiofiles==0.5.0 | |
aiohttp==3.6.2 | |
async-timeout==3.0.1 | |
attrs==19.3.0 | |
autopep8==1.5.1 | |
cffi==1.14.0 | |
chardet==3.0.4 | |
colorama==0.4.3 | |
idna==2.9 | |
multidict==4.7.5 | |
pep8==1.7.1 | |
pkg-resources==0.0.0 | |
pycares==3.1.1 | |
pycodestyle==2.5.0 | |
pycparser==2.20 | |
yarl==1.4.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment