diff --git a/README.md b/README.md index c7ef13c1..17ebf4e3 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ Passive: * pentesttools: Powerful Penetration Testing Tools, Easy to Use (Needs an API key and is not free for API access) - https://pentest-tools.com/home +* projecdiscovery: We actively collect and maintain internet-wide assets data, +to enhance research and analyse changes around DNS for better insights - https://chaos.projectdiscovery.io +(Requires an API key) + * qwant: Qwant search engine - www.qwant.com * rapiddns: DNS query tool which make querying subdomains or sites of a same IP easy! https://rapiddns.io @@ -94,6 +98,7 @@ Documentation to setup API keys can be found at - https://github.com/laramies/th * hunter - limited to 10 on the free plan so you will ned to do -l 10 switch * intelx * pentesttools +* projecdiscovery - invite only for now * securityTrails * shodan * spyse - need to have a paid account be able to use the api now diff --git a/api-keys.yaml b/api-keys.yaml index 4c56de55..49737a7a 100644 --- a/api-keys.yaml +++ b/api-keys.yaml @@ -12,7 +12,10 @@ apikeys: key: 9df61df0-84f7-4dc7-b34c-8ccfb8646ace pentestTools: - key: + key: + + projectDiscovery: + key: securityTrails: key: diff --git a/theHarvester/__main__.py b/theHarvester/__main__.py index 809ea3d3..7c4252b1 100644 --- a/theHarvester/__main__.py +++ b/theHarvester/__main__.py @@ -34,7 +34,8 @@ async def start(): parser.add_argument('-f', '--filename', help='Save the results to an HTML and/or XML file.', default='', type=str) parser.add_argument('-b', '--source', help='''baidu, bing, bingapi, bufferoverun, certspotter, crtsh, dnsdumpster, duckduckgo, exalead, github-code, google, - hackertarget, hunter, intelx, linkedin, linkedin_links, netcraft, otx, pentesttools, + hackertarget, hunter, intelx, linkedin, linkedin_links, + netcraft, otx, pentesttools, projectdiscovery, qwant, rapiddns, securityTrails, spyse, sublist3r, threatcrowd, threatminer, trello, twitter, urlscan, virustotal, yahoo''') @@ -301,6 +302,17 @@ async def start(): else: print(f'An exception has occurred in PentestTools search: {e}') + elif engineitem == 'projectdiscovery': + from theHarvester.discovery import projectdiscovery + try: + projectdiscovery_search = projectdiscovery.SearchDiscovery(word) + stor_lst.append(store(projectdiscovery_search, engineitem, store_host=True)) + except Exception as e: + if isinstance(e, MissingKey): + print(e) + else: + print(f'An exception has occurred in ProjectDiscovery search: {e}') + elif engineitem == 'qwant': from theHarvester.discovery import qwantsearch qwant_search = qwantsearch.SearchQwant(word, start, limit) diff --git a/theHarvester/discovery/projectdiscovery.py b/theHarvester/discovery/projectdiscovery.py new file mode 100644 index 00000000..d31aacba --- /dev/null +++ b/theHarvester/discovery/projectdiscovery.py @@ -0,0 +1,27 @@ +from theHarvester.discovery.constants import * +from theHarvester.lib.core import * + + +class SearchDiscovery: + + def __init__(self, word): + self.word = word + self.key = Core.projectdiscovery_key() + if self.key is None: + raise MissingKey(True) + self.total_results = None + self.proxy = False + + async def do_search(self): + url = f'https://dns.projectdiscovery.io/dns/{self.word}/subdomains' + response = await AsyncFetcher.fetch_all([url], json=True, headers={'User-Agent': Core.get_user_agent(), + 'Authorization': self.key}, + proxy=self.proxy) + self.total_results = [f'{domains}.{self.word}' for domains in response[0]['subdomains']] + + async def get_hostnames(self) -> set: + return self.total_results + + async def process(self, proxy=False): + self.proxy = proxy + await self.do_search() diff --git a/theHarvester/lib/core.py b/theHarvester/lib/core.py index 9c2d99ef..8029d2c7 100644 --- a/theHarvester/lib/core.py +++ b/theHarvester/lib/core.py @@ -12,7 +12,7 @@ import certifi class Core: @staticmethod def version() -> str: - return '3.2.0dev7' + return '3.2.0dev8' @staticmethod def bing_key() -> str: @@ -69,6 +69,17 @@ class Core: return keys['apikeys']['pentestTools']['key'] return keys['apikeys']['pentestTools']['key'] + @staticmethod + def projectdiscovery_key() -> str: + try: + with open('/etc/theHarvester/api-keys.yaml', 'r') as api_keys: + keys = yaml.safe_load(api_keys) + except FileNotFoundError: + with open('api-keys.yaml', 'r') as api_keys: + keys = yaml.safe_load(api_keys) + return keys['apikeys']['projectDiscovery']['key'] + return keys['apikeys']['projectDiscovery']['key'] + @staticmethod def security_trails_key() -> str: try: @@ -152,6 +163,7 @@ class Core: 'netcraft', 'otx', 'pentesttools', + 'projectdiscovery', 'qwant', 'rapiddns', 'securityTrails',