├── .gitattributes ├── README.md └── eaas.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Enumeration as a Service 2 | 3 | ## Description 4 | 5 | Enumeration as a Service (eaas.py) in a script that queries the DNS server of a particular domain looking for indications that the domain may be utilizing SaaS offerings. This analysis is performed on TXT, CNAME, A and MX Records. Query results, as well as highlighted results of interest are returned to the user. 6 | 7 | ## Usage 8 | 9 | `./eaas.py ` 10 | 11 | ## To Do 12 | 13 | - Add known IP address ranges for lookups for SPF records (currently reliant on DNS) 14 | - Checking for dependencies and prompting for install if not available on current machine 15 | - Add "Verbose Mode" to allow user to decide whether or they want detailed responses 16 | - Summary of findings at the end of the query for easier viewing 17 | - Add any additional SaaS offerings which may have been overlooked (There are likely _many_) 18 | 19 | ## Current Checks 20 | 21 | #### Google 22 | - `google-site-verification` TXT Record [Documentation] 23 | - `google.com` in SPF Record 24 | - `google.com` in MX Record 25 | - `googlemail.com` in MX Record 26 | - A records which have the term `GOOGLE` in the ASN Provider 27 | - CNAME records that point to `lync.com` 28 | 29 | #### Microsoft 30 | - `MS` TXT record [Documentation](https://support.office.com/en-us/article/gather-the-information-you-need-to-create-office-365-dns-records-77f90d4a-dc7f-4f09-8972-c1b03ea85a67) 31 | - CNAME Record pointing to `outlook` 32 | - `protection.outlook.com` in SPF record 33 | - `protection.outlook.com` in SPF Record 34 | - A records which have the term `MICROSOFT` in the ASN Provider 35 | 36 | ##### DocuSign 37 | - `docusign` TXT Record [Documentation](https://support.docusign.com/en/guides/org-admin-guide-domains) 38 | 39 | #### Facebook 40 | - `facebook-domain-verification` TXT Record [Documentation](https://developers.facebook.com/docs/sharing/domain-verification/) 41 | 42 | #### Adobe 43 | - `adobe-sign-verification` TXT Record [Documentation](https://helpx.adobe.com/sign/help/domain_claiming.html) 44 | - `adobe-idp-site-verification` TXT Record [Documentation](https://helpx.adobe.com/ca/enterprise/using/verify-domain-ownership.html) 45 | 46 | #### Atlassian 47 | - `atlassian-domain-verification` TXT Record [Documentation](https://confluence.atlassian.com/cloud/domain-verification-873871234.html) 48 | 49 | #### Yandex 50 | - `yandex-verification` TXT Record 51 | 52 | #### Amazon 53 | - `_amazonses` TXT Record [Documentation](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/dns-txt-records.html) 54 | 55 | #### LogMeIn 56 | - `logmein-verification-code` TXT Record [Documentation](https://support.logmeininc.com/gotomeeting/help/set-up-domains-g2m710101) 57 | 58 | #### Citrix 59 | - `citrix-verification-code` TXT Record 60 | 61 | #### Salesforce / Pardot 62 | - `pardot` TXT Record 63 | - `salesforce.com` in SPF Record 64 | 65 | #### Zuora 66 | - `zuora` TXT Record 67 | 68 | #### AirWatch 69 | - A records which have `AirWatch LLC` in ASN Provider 70 | - CNAME records that point to `awmdm.com` 71 | 72 | #### ProofPoint 73 | - `pphosted.com` in SPF Record 74 | - `pphosted` in MX Record 75 | 76 | #### Service Now 77 | - `service-now.com` in SPF Record 78 | 79 | #### NetSuite 80 | - `mailsenders.netsuite.com` in SPF Record 81 | 82 | #### Marketo 83 | - `mktomail.com` in SPF Record 84 | 85 | #### MailChimp / Mandrill 86 | - `spf.mandrillapp.com` in SPF Record 87 | - `mcsv.net` in SPF Record 88 | 89 | #### ZenDesk 90 | - `zendesk.com` in SPF Record 91 | 92 | #### FreshDesk 93 | - `freshdesk.com` in SPF Record 94 | 95 | #### ZOHO 96 | - `zoho.com` in MX Record -------------------------------------------------------------------------------- /eaas.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | import dns.resolver, warnings,sys 3 | from ipwhois import IPWhois 4 | 5 | domain = sys.argv[1] 6 | 7 | txtrecords = { 8 | "docusign":"This record is used as proof of domain ownership for DocuSign product offerings. This indicates the domain likely uses DocuSign as an e-signature solution.", 9 | "facebook-domain-verification":"This record is used as proof of domain ownership for use in the Facebook Business Manager.", 10 | "google-site-verification":"This record is used as proof of ownership for Google G Suite product offerings, however it might simply be verification for Google Analytics.", 11 | "adobe-sign-verification":"This record is used as proof of ownership of a domain for the Adobe Sign product offering. This indicates the domain likely uses Adobe Sign as an e-signature solution.", 12 | "atlassian-domain-verification":"This record verifies domain ownership with Atlassian. This indicates the domain might be sending managed emails from an Atlassian property and likely utilizes Atalassian product offerings such as Jira of Confluence.", 13 | "MS":"This record is used as proof of domain ownership by the Microsoft Office 365 product offering. This indicates a probable usage of at least some Office 365 products.", 14 | "adobe-idp-site-verification":"This record is used as proof of ownership for use in the Adobe Enterprise Products product offerings.", 15 | "yandex-verification":"This record is used as proof of ownership of a domain for Yandex. This indicates a probable usage of the Yandex Webmaster Tools.", 16 | "_amazonses":"Amazon Simple Email Services", 17 | "logmein-verification-code":"This record is used as proof of ownership for a domain for LogMeIn services. The presence of this record indicates the owner of the domain is likely using LogMeIn for remote troubleshooting.", 18 | "citrix-verification-code":"This record indicates the domain might be associated with utilizing Citrix Services.", 19 | "pardot":"This record indicates the domain might be utilizing Pardot B2B Marketing tools from Salesforce.com.", 20 | "zuora":"This record indicates the domain might be utilizing Zuora subscription management software." 21 | } 22 | 23 | cnamerecords = { 24 | "autodiscover.":"This domain appears to be outsourcing Microsoft Exchange.", 25 | "lyncdiscover.":"This domain appears to be outsourcing Microsoft Lync.", 26 | "sip.":"This domain appears to be outsourcing Microsoft SIP Services.", 27 | "enterpriseregistration.":"This domain appears to be outsourcing Mobile Device Management (MDM) services.", 28 | "enterpriseenrollment.":"This domain appears to be outsourcing Mobile Device Management (MDM) services.", 29 | "adfs.":"Active Directory Federated Services", 30 | "sts.":"Security Token Service" 31 | } 32 | 33 | asnproviders = { 34 | "MICROSOFT":"Microsoft Corporation", 35 | "GOOGLE":"Google (Alphabet) Corporation", 36 | "AirWatch LLC":"AirWatch Mobile Device Management" 37 | } 38 | 39 | cnameproviders = { 40 | "outlook":"Microsoft Office 365 (Managed Exchange)", 41 | "awmdm.com":"Airwatch Mobile Device Management (MDM)", 42 | "lync.com":"Microsoft Hosted Lync" 43 | } 44 | 45 | spfrecords = { 46 | "_spf.salesforce.com":"Domain is allowing emails to be sent from Salesforce.com. This indicates a high liklihood of subscription to Salesforce services.", 47 | "_spf.google.com":"Domain is allowing emails to be sent from Google.com. This indicates the domain may utilize Gmail or other G-Suite product offerings.", 48 | "protection.outlook.com":"Domain is allowing emails to be sent from Microsoft.com. This strongly indicates the domain is utilzing Microsoft Hosted Exchange.", 49 | "service-now.com":"Domain is allowing emails to be sent from service-now.com. This strongly indicates the domain is using the Service Now helpdesk platform.", 50 | "mailsenders.netsuite.com":"Domain is allowing emails to be sent from NetSuite. This strongly indicates the domain is using NetSuite product offerings (ERP / Cloud Accounting).", 51 | "mktomail.com":"Domain is allowing emails to be sent from Marketo. This strongly indicates the domain is using the Marketo Marketing and Lead Generation platform.", 52 | "spf.mandrillapp.com":"Domain is allowing emails to be sent from Mandrill (MailChimp). This strongly indicates the domain is using the Mandrill product offering for transactional email.", 53 | "pphosted.com":"Domain is allowing emails to be sent from Proof Point. This strongly indicates the domain is utilizing Proof Point Managed email services.", 54 | "zendesk.com":"Domain is allowing emails to be sent from Zendesk. This strongly indicates the domain is utilizing Zendesk for help desk and ticketing purposes.", 55 | "mcsv.net":"Domain is allowing emails to be sent from MailChimp. This strongly indicates the domain is utilizing MailChimp for email marketing.", 56 | "freshdesk.com":"Domain is allowing emails to be sent from Freshdesk. This strongly indicates the domain is utilizing FreshDesk for helpdesk and ticketing services." 57 | } 58 | 59 | mxrecords = { 60 | "google.com":"Google server as an email server.\n └── [*] This strongly indicates the domain is utilizing Google as an email server.", 61 | "googlemail.com":"Google server as an email server.\n └── [*] This strongly indicates the domain is utilizing Google as an email server.", 62 | "pphosted.com":"Proof Point server as an email server.\n └── [*] This strongly indicates that Proof Point Managed Email Hosting is being used.", 63 | "zoho.com":"ZOHO server as an email server.\n └── [*] This strongly indicates that ZOHO is being utilized for email services.", 64 | "protection.outlook.com":"Microsoft server as an email server.\n └── [*] This strongly indicates the domain is utilzing Microsoft Hosted Exchange." 65 | } 66 | 67 | misctxt = { 68 | "pardot":"Pardot Business-to-Business Marketing by Salesforce" 69 | } 70 | 71 | def displayhelp(): 72 | print("EaaS - Enumeration as a Service.") 73 | print("Usage : ./eaas.py [domain]") 74 | 75 | # Function to query TXT DNS entries 76 | def querytxt(): 77 | print("\n") 78 | print("[*] Querying TXT DNS entries.") 79 | print("=========================================================") 80 | answers = dns.resolver.resolve(domain,"TXT") 81 | for rdata in answers: 82 | # Examine various TXT based records for the domain 83 | for key, value in txtrecords.items(): 84 | if key in rdata.to_text(): 85 | print("[INFO] \033[33m\"{}\"\033[0;0m Record Found.".format(key)) 86 | print(" └── \033[32m[+]\033[0;0m {}".format(value)) 87 | # Examine SPF records for the domain 88 | for spfkey, spfvalue in spfrecords.items(): 89 | if spfkey in rdata.to_text(): 90 | print("[INFO] \033[33m\"{}\"\033[0;0m SPF Record found.\n └── \033[32m[+]\033[0;0m {}".format(spfkey,spfvalue)) 91 | 92 | # Function to query and examine CNAME records for the chosen domain 93 | def querycname(): 94 | print("\n") 95 | print("[*] Querying CNAME DNS entries.") 96 | print("=========================================================") 97 | for key, value in cnamerecords.items(): 98 | lookup = key + domain 99 | try: 100 | answers = dns.resolver.resolve(lookup, 'CNAME') 101 | for rdata in answers: 102 | print("[INFO] \033[33m\"{}\"\033[0;0m CNAME record found.".format(key[:-1])) 103 | print(" └── [INFO] CNAME record points to \033[33m{}\033[0;0m".format(rdata.target)) 104 | for cnamekey, cnamevalue in cnameproviders.items(): 105 | if cnamekey in rdata.target.to_text(): 106 | print(" └── \033[32m[+]\033[0;0m Domain appears to be outsourcing services to \033[33m{}\033[0;0m.".format(cnamevalue)) 107 | except: 108 | pass 109 | 110 | # Function to query and exmaine A records for the chosen domain. 111 | def queryarecords(): 112 | print("\n") 113 | print("[*] Querying A record DNS entries.") 114 | print("=========================================================") 115 | for key, value in cnamerecords.items(): 116 | lookup = key + domain 117 | try: 118 | answers = dns.resolver.resolve(lookup, 'A') 119 | for rdata in answers: 120 | print("[INFO] \033[33m\"{}\"\033[0;0m Record Found resolving to \033[33m{}\033[0;0m.".format(key[:-1],rdata.address)) 121 | with warnings.catch_warnings(): 122 | warnings.filterwarnings("ignore", category=UserWarning) 123 | obj = IPWhois(str(rdata.address)) 124 | results = obj.lookup_rdap() 125 | print(" └── [INFO] IP Address resolves to an ASN owned by \033[33m{}\033[0;0m".format(results['asn_description'])) 126 | for asnkey, asnvalue in asnproviders.items(): 127 | if asnkey in format(results['asn_description']): 128 | print(" └── \033[32m[+]\033[0;0m {} Services appear to be provided by \033[33m{}\033[0;0m.".format(value,asnvalue)) 129 | except: 130 | pass 131 | 132 | # Function to query and examine the MX records for the chosen domain. 133 | def querymxrecords(): 134 | print("\n") 135 | print("[*] Querying MX record DNS entries.") 136 | print("=========================================================") 137 | try: 138 | answers = dns.resolver.resolve(domain, 'MX') 139 | for rdata in answers: 140 | print("[INFO] MX Record : \033[33m{}\033[0;0m".format(rdata.exchange)) 141 | for mxkey, mxvalue in mxrecords.items(): 142 | if mxkey in rdata.exchange.to_text(): 143 | print(" └── \033[32m[+]\033[0;0m : This MX Record indicates a strong probability that the domain is using a {} for hosted email solutions, however it might just be using the MX for mail filtering.".format(mxvalue)) 144 | except: 145 | pass 146 | 147 | if __name__ == "__main__": 148 | if len(sys.argv) == 1: 149 | displayhelp() 150 | sys.exit() 151 | else: 152 | print("[*] EaaS - Enumeration as a Service script started.") 153 | print("[*] Performing queries on domain \033[33m{}\033[0;0m".format(domain)) 154 | querytxt() 155 | querycname() 156 | queryarecords() 157 | querymxrecords() --------------------------------------------------------------------------------