-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathcensys_enumeration.py
148 lines (129 loc) · 5.65 KB
/
censys_enumeration.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
# A script to extract subdomains/emails from related SSL/TLS certificates using Censys
# You'll need Censys API ID and API Secret to be able to extract SSL/TLS certificates
# Needs censys module to run. pip install censys.
from __future__ import print_function
import logging
import re
import os
import sys
import json
logging.basicConfig(
level=logging.INFO,
format="%(message)s"
)
__author__ = "Bharath(github.com/yamakira)"
__version__ = "0.1"
__purpose__ = '''Extract subdomains/emails for a domain from censys SSL/TLS certificate dataset'''
CENSYS_API_ID = os.environ['CENSYS_API_ID'] # Add CENSYS_API_ID as environment variable
CENSYS_API_SECRET = os.environ['CENSYS_API_SECRET'] # Add CENSYS_API_SECRET as environment variable
try:
import censys.certificates
import censys.ipv4
except ImportError:
logging.info("\033[1;31m[!] Failed to import censys module. Run 'pip install censys'\033[1;m")
sys.exit()
try:
import click
except ImportError:
logging.info("\033[1;31m[!] Failed to import click module. Run 'pip install click'\033[1;m")
sys.exit()
json_report = {}
emails_found = []
subdomains_found = []
def get_certificates():
try:
if not CENSYS_API_ID or not CENSYS_API_SECRET:
logging.info("\033[1;31m[!] API KEY or Secret for Censys not provided.\033[1;m" \
"\nYou'll have to provide them in the script")
sys.exit()
logging.info("[+] Extracting certificates using Censys")
censys_certificates = censys.certificates.CensysCertificates(CENSYS_API_ID, CENSYS_API_SECRET)
return censys_certificates
except censys.base.CensysUnauthorizedException:
logging.info('\033[93m[!] Your Censys credentials look invalid.\n\033[1;m')
sys.exit(1)
except censys.base.CensysRateLimitExceededException:
logging.info('\033[93m[!] Looks like you exceeded your Censys account limits rate. Exiting\n\033[1;m')
sys.exit(1)
def get_subdomains(domain, certificates):
unique_subdomains = []
logging.info("[+] Extracting sub-domains for {} from certificates".format(domain.rstrip()))
try:
certificate_query = 'parsed.names: {}'.format(domain)
certificates_search_results = certificates.search(certificate_query, fields=['parsed.names'])
except CensysException:
logging.info('\033[93m[!] Error while fetching results from Censys.\n\033[1;m')
sys.exit(1)
for search_result in certificates_search_results:
subdomains_found.extend(search_result['parsed.names'])
for subdomain in subdomains_found:
if '*' not in subdomain and subdomain.endswith(domain):
unique_subdomains.append(subdomain)
return set(unique_subdomains)
def get_emails(domain, certificates):
del emails_found[:]
logging.info("[+] Extracting emails belonging to {} from SSL/TLS certificates".format(domain.rstrip()))
certificate_query = 'parsed.names: {}'.format(domain)
try:
certificates_search_results = certificates.search(certificate_query, fields=['parsed.subject.email_address'])
except KeyError:
pass
for search_result in certificates_search_results:
try:
emails_found.extend(search_result['parsed.subject.email_address'])
except KeyError:
pass
return set(emails_found)
def print_subdomains(subdomains_found, domain):
if len(subdomains_found) is 0:
logging.info('[!] Did not find any email addresses')
return
logging.info("\033[92m[+] Total unique subdomains found for {}: {}\033[1;m".format(domain, len(subdomains_found)))
for subdomain in sorted(subdomains_found):
print(subdomain)
def print_emails(emails_found, domain):
if len(emails_found) is 0:
logging.info('[!] Did not find any email addresses')
return
logging.info("\033[92m[+] Total unique emails found for {}: {}\033[1;m".format(domain, len(emails_found)))
for email in sorted(emails_found):
print(email)
def write_to_json(domain):
with open('json_report.json', 'w') as outfile:
json.dump(json_report, outfile, default=str)
file_path = os.path.abspath(outfile.name)
logging.info("\033[1;32m[+] JSON results written to : {}\033[1;m".format(file_path))
def get_domains(domain_names_file):
with open(domain_names_file) as f:
domains = f.readlines()
return domains
@click.command()
@click.argument('file',type=click.Path(exists=True))
@click.option('--verbose', is_flag=True,
help="Verbose output")
@click.option('--subdomains/--no-subdomains', default=True,
help='Enable/Disable subdomain enumeration')
@click.option('--emails/--no-emails', default=True,
help='Enable/Disable email enumeration')
def main(emails, subdomains, verbose, file):
domains = get_domains(file)
certificates = get_certificates()
for domain in domains:
domain = domain.rstrip()
if emails == True: # Only if emails enumration is enabled
emails_found = get_emails(domain,certificates)
if verbose:
print_emails(emails_found, domain)
else:
print("[*] Email enumeration disabled")
if subdomains == True: # Only if sudomain enumration is enabled
subdomains_found = get_subdomains(domain,certificates)
if verbose:
print_subdomains(subdomains_found, domain)
else:
print("[*] Subdomain enumeration disabled")
json_report[domain] = {"domain":domain,"emails":list(emails_found), "subdomains":list(subdomains_found)}
write_to_json(domain) # Write the JSON report to file
if __name__ == '__main__':
main()