Skip to content

Instantly share code, notes, and snippets.

@daddycocoaman
Last active August 10, 2021 17:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daddycocoaman/3438d33b511ef2dbe1eb38cd66c782e6 to your computer and use it in GitHub Desktop.
Save daddycocoaman/3438d33b511ef2dbe1eb38cd66c782e6 to your computer and use it in GitHub Desktop.
Async CNAME Enumeration (WIP)
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())
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