Advertisement
Guest User

Untitled

a guest
May 28th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.13 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. # Sublist3r v1.0
  4. # By Ahmed Aboul-Ela - twitter.com/aboul3la
  5.  
  6. # modules in standard library
  7. import re
  8. import sys
  9. import os
  10. import argparse
  11. import time
  12. import hashlib
  13. import random
  14. import multiprocessing
  15. import threading
  16. import socket
  17. import json
  18. from collections import Counter
  19.  
  20. # external modules
  21. from subbrute import subbrute
  22. import dns.resolver
  23. import requests
  24.  
  25. # Python 2.x and 3.x compatiablity
  26. if sys.version > '3':
  27. import urllib.parse as urlparse
  28. import urllib.parse as urllib
  29. else:
  30. import urlparse
  31. import urllib
  32.  
  33. # In case you cannot install some of the required development packages
  34. # there's also an option to disable the SSL warning:
  35. try:
  36. import requests.packages.urllib3
  37. requests.packages.urllib3.disable_warnings()
  38. except:
  39. pass
  40.  
  41. # Check if we are running this on windows platform
  42. is_windows = sys.platform.startswith('win')
  43.  
  44. # Console Colors
  45. if is_windows:
  46. # Windows deserves coloring too :D
  47. G = '\033[92m' # green
  48. Y = '\033[93m' # yellow
  49. B = '\033[94m' # blue
  50. R = '\033[91m' # red
  51. W = '\033[0m' # white
  52. try:
  53. import win_unicode_console , colorama
  54. win_unicode_console.enable()
  55. colorama.init()
  56. #Now the unicode will work ^_^
  57. except:
  58. print("[!] Error: Coloring libraries not installed, no coloring will be used [Check the readme]")
  59. G = Y = B = R = W = G = Y = B = R = W = ''
  60.  
  61.  
  62. else:
  63. G = '\033[92m' # green
  64. Y = '\033[93m' # yellow
  65. B = '\033[94m' # blue
  66. R = '\033[91m' # red
  67. W = '\033[0m' # white
  68.  
  69.  
  70. def banner():
  71. print("""%s
  72. ____ _ _ _ _ _____
  73. / ___| _ _| |__ | (_)___| |_|___ / _ __
  74. \___ \| | | | '_ \| | / __| __| |_ \| '__|
  75. ___) | |_| | |_) | | \__ \ |_ ___) | |
  76. |____/ \__,_|_.__/|_|_|___/\__|____/|_|%s%s
  77.  
  78. # Coded By Ahmed Aboul-Ela - @aboul3la
  79. """ % (R, W, Y))
  80.  
  81.  
  82. def parser_error(errmsg):
  83. banner()
  84. print("Usage: python " + sys.argv[0] + " [Options] use -h for help")
  85. print(R + "Error: " + errmsg + W)
  86. sys.exit()
  87.  
  88.  
  89. def parse_args():
  90. # parse the arguments
  91. parser = argparse.ArgumentParser(epilog='\tExample: \r\npython ' + sys.argv[0] + " -d google.com")
  92. parser.error = parser_error
  93. parser._optionals.title = "OPTIONS"
  94. parser.add_argument('-d', '--domain', help="Domain name to enumerate it's subdomains", required=True)
  95. parser.add_argument('-b', '--bruteforce', help='Enable the subbrute bruteforce module', nargs='?', default=False)
  96. parser.add_argument('-p', '--ports', help='Scan the found subdomains against specified tcp ports')
  97. parser.add_argument('-v', '--verbose', help='Enable Verbosity and display results in realtime', nargs='?', default=False)
  98. parser.add_argument('-t', '--threads', help='Number of threads to use for subbrute bruteforce', type=int, default=30)
  99. parser.add_argument('-e', '--engines', help='Specify a comma-separated list of search engines')
  100. parser.add_argument('-o', '--output', help='Save the results to text file')
  101. return parser.parse_args()
  102.  
  103.  
  104. def write_file(filename, subdomains):
  105. # saving subdomains results to output file
  106. print("%s[-] Saving results to file: %s%s%s%s" % (Y, W, R, filename, W))
  107. with open(str(filename), 'wt') as f:
  108. for subdomain in subdomains:
  109. f.write(subdomain + os.linesep)
  110.  
  111.  
  112. def subdomain_sorting_key(hostname):
  113. """Sorting key for subdomains
  114.  
  115. This sorting key orders subdomains from the top-level domain at the right
  116. reading left, then moving '^' and 'www' to the top of their group. For
  117. example, the following list is sorted correctly:
  118.  
  119. [
  120. 'example.com',
  121. 'www.example.com',
  122. 'a.example.com',
  123. 'www.a.example.com',
  124. 'b.a.example.com',
  125. 'b.example.com',
  126. 'example.net',
  127. 'www.example.net',
  128. 'a.example.net',
  129. ]
  130.  
  131. """
  132. parts = hostname.split('.')[::-1]
  133. if parts[-1] == 'www':
  134. return parts[:-1], 1
  135. return parts, 0
  136.  
  137.  
  138. class enumratorBase(object):
  139. def __init__(self, base_url, engine_name, domain, subdomains=None, silent=False, verbose=True):
  140. subdomains = subdomains or []
  141. self.domain = urlparse.urlparse(domain).netloc
  142. self.session = requests.Session()
  143. self.subdomains = []
  144. self.timeout = 25
  145. self.base_url = base_url
  146. self.engine_name = engine_name
  147. self.silent = silent
  148. self.verbose = verbose
  149. self.headers = {
  150. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
  151. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  152. 'Accept-Language': 'en-US,en;q=0.8',
  153. 'Accept-Encoding': 'gzip',
  154. }
  155. self.print_banner()
  156.  
  157. def print_(self, text):
  158. if not self.silent:
  159. print(text)
  160. return
  161.  
  162. def print_banner(self):
  163. """ subclass can override this if they want a fancy banner :)"""
  164. self.print_(G + "[-] Searching now in %s.." % (self.engine_name) + W)
  165. return
  166.  
  167. def send_req(self, query, page_no=1):
  168.  
  169. url = self.base_url.format(query=query, page_no=page_no)
  170. try:
  171. resp = self.session.get(url, headers=self.headers, timeout=self.timeout)
  172. except Exception:
  173. resp = None
  174. return self.get_response(resp)
  175.  
  176. def get_response(self, response):
  177. if response is None:
  178. return 0
  179. return response.text if hasattr(response, "text") else response.content
  180.  
  181. def check_max_subdomains(self, count):
  182. if self.MAX_DOMAINS == 0:
  183. return False
  184. return count >= self.MAX_DOMAINS
  185.  
  186. def check_max_pages(self, num):
  187. if self.MAX_PAGES == 0:
  188. return False
  189. return num >= self.MAX_PAGES
  190.  
  191. # override
  192. def extract_domains(self, resp):
  193. """ chlid class should override this function """
  194. return
  195.  
  196. # override
  197. def check_response_errors(self, resp):
  198. """ chlid class should override this function
  199. The function should return True if there are no errors and False otherwise
  200. """
  201. return True
  202.  
  203. def should_sleep(self):
  204. """Some enumrators require sleeping to avoid bot detections like Google enumerator"""
  205. return
  206.  
  207. def generate_query(self):
  208. """ chlid class should override this function """
  209. return
  210.  
  211. def get_page(self, num):
  212. """ chlid class that user different pagnation counter should override this function """
  213. return num + 10
  214.  
  215. def enumerate(self, altquery=False):
  216. flag = True
  217. page_no = 0
  218. prev_links = []
  219. retries = 0
  220.  
  221. while flag:
  222. query = self.generate_query()
  223. count = query.count(self.domain) # finding the number of subdomains found so far
  224.  
  225. # if they we reached the maximum number of subdomains in search query
  226. # then we should go over the pages
  227. if self.check_max_subdomains(count):
  228. page_no = self.get_page(page_no)
  229.  
  230. if self.check_max_pages(page_no): # maximum pages for Google to avoid getting blocked
  231. return self.subdomains
  232. resp = self.send_req(query, page_no)
  233.  
  234. # check if there is any error occured
  235. if not self.check_response_errors(resp):
  236. return self.subdomains
  237. links = self.extract_domains(resp)
  238.  
  239. # if the previous page hyperlinks was the similar to the current one, then maybe we have reached the last page
  240. if links == prev_links:
  241. retries += 1
  242. page_no = self.get_page(page_no)
  243.  
  244. # make another retry maybe it isn't the last page
  245. if retries >= 3:
  246. return self.subdomains
  247.  
  248. prev_links = links
  249. self.should_sleep()
  250.  
  251. return self.subdomains
  252.  
  253.  
  254. class enumratorBaseThreaded(multiprocessing.Process, enumratorBase):
  255. def __init__(self, base_url, engine_name, domain, subdomains=None, q=None, lock=threading.Lock(), silent=False, verbose=True):
  256. subdomains = subdomains or []
  257. enumratorBase.__init__(self, base_url, engine_name, domain, subdomains, silent=silent, verbose=verbose)
  258. multiprocessing.Process.__init__(self)
  259. self.lock = lock
  260. self.q = q
  261. return
  262.  
  263. def run(self):
  264. domain_list = self.enumerate()
  265. for domain in domain_list:
  266. self.q.append(domain)
  267.  
  268.  
  269. class GoogleEnum(enumratorBaseThreaded):
  270. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  271. subdomains = subdomains or []
  272. base_url = "https://google.com/search?q={query}&btnG=Search&hl=en-US&biw=&bih=&gbv=1&start={page_no}&filter=0"
  273. self.engine_name = "Google"
  274. self.MAX_DOMAINS = 11
  275. self.MAX_PAGES = 200
  276. super(GoogleEnum, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  277. self.q = q
  278. return
  279.  
  280. def extract_domains(self, resp):
  281. links_list = list()
  282. link_regx = re.compile('<cite.*?>(.*?)<\/cite>')
  283. try:
  284. links_list = link_regx.findall(resp)
  285. for link in links_list:
  286. link = re.sub('<span.*>', '', link)
  287. if not link.startswith('http'):
  288. link = "http://" + link
  289. subdomain = urlparse.urlparse(link).netloc
  290. if subdomain and subdomain not in self.subdomains and subdomain != self.domain:
  291. if self.verbose:
  292. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  293. self.subdomains.append(subdomain.strip())
  294. except Exception:
  295. pass
  296. return links_list
  297.  
  298. def check_response_errors(self, resp):
  299. if (type(resp) is str or type(resp) is unicode) and 'Our systems have detected unusual traffic' in resp:
  300. self.print_(R + "[!] Error: Google probably now is blocking our requests" + W)
  301. self.print_(R + "[~] Finished now the Google Enumeration ..." + W)
  302. return False
  303. return True
  304.  
  305. def should_sleep(self):
  306. time.sleep(5)
  307. return
  308.  
  309. def generate_query(self):
  310. if self.subdomains:
  311. fmt = 'site:{domain} -www.{domain} -{found}'
  312. found = ' -'.join(self.subdomains[:self.MAX_DOMAINS - 2])
  313. query = fmt.format(domain=self.domain, found=found)
  314. else:
  315. query = "site:{domain} -www.{domain}".format(domain=self.domain)
  316. return query
  317.  
  318.  
  319. class YahooEnum(enumratorBaseThreaded):
  320. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  321. subdomains = subdomains or []
  322. base_url = "https://search.yahoo.com/search?p={query}&b={page_no}"
  323. self.engine_name = "Yahoo"
  324. self.MAX_DOMAINS = 10
  325. self.MAX_PAGES = 0
  326. super(YahooEnum, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  327. self.q = q
  328. return
  329.  
  330. def extract_domains(self, resp):
  331. link_regx2 = re.compile('<span class=" fz-.*? fw-m fc-12th wr-bw.*?">(.*?)</span>')
  332. link_regx = re.compile('<span class="txt"><span class=" cite fw-xl fz-15px">(.*?)</span>')
  333. links_list = []
  334. try:
  335. links = link_regx.findall(resp)
  336. links2 = link_regx2.findall(resp)
  337. links_list = links + links2
  338. for link in links_list:
  339. link = re.sub("<(\/)?b>", "", link)
  340. if not link.startswith('http'):
  341. link = "http://" + link
  342. subdomain = urlparse.urlparse(link).netloc
  343. if not subdomain.endswith(self.domain):
  344. continue
  345. if subdomain and subdomain not in self.subdomains and subdomain != self.domain:
  346. if self.verbose:
  347. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  348. self.subdomains.append(subdomain.strip())
  349. except Exception:
  350. pass
  351.  
  352. return links_list
  353.  
  354. def should_sleep(self):
  355. return
  356.  
  357. def get_page(self, num):
  358. return num + 10
  359.  
  360. def generate_query(self):
  361. if self.subdomains:
  362. fmt = 'site:{domain} -domain:www.{domain} -domain:{found}'
  363. found = ' -domain:'.join(self.subdomains[:77])
  364. query = fmt.format(domain=self.domain, found=found)
  365. else:
  366. query = "site:{domain}".format(domain=self.domain)
  367. return query
  368.  
  369.  
  370. class AskEnum(enumratorBaseThreaded):
  371. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  372. subdomains = subdomains or []
  373. base_url = 'http://www.ask.com/web?q={query}&page={page_no}&qid=8D6EE6BF52E0C04527E51F64F22C4534&o=0&l=dir&qsrc=998&qo=pagination'
  374. self.engine_name = "Ask"
  375. self.MAX_DOMAINS = 11
  376. self.MAX_PAGES = 0
  377. enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  378. self.q = q
  379. return
  380.  
  381. def extract_domains(self, resp):
  382. links_list = list()
  383. link_regx = re.compile('<p class="web-result-url">(.*?)</p>')
  384. try:
  385. links_list = link_regx.findall(resp)
  386. for link in links_list:
  387. if not link.startswith('http'):
  388. link = "http://" + link
  389. subdomain = urlparse.urlparse(link).netloc
  390. if subdomain not in self.subdomains and subdomain != self.domain:
  391. if self.verbose:
  392. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  393. self.subdomains.append(subdomain.strip())
  394. except Exception:
  395. pass
  396.  
  397. return links_list
  398.  
  399. def get_page(self, num):
  400. return num + 1
  401.  
  402. def generate_query(self):
  403. if self.subdomains:
  404. fmt = 'site:{domain} -www.{domain} -{found}'
  405. found = ' -'.join(self.subdomains[:self.MAX_DOMAINS])
  406. query = fmt.format(domain=self.domain, found=found)
  407. else:
  408. query = "site:{domain} -www.{domain}".format(domain=self.domain)
  409.  
  410. return query
  411.  
  412.  
  413. class BingEnum(enumratorBaseThreaded):
  414. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  415. subdomains = subdomains or []
  416. base_url = 'https://www.bing.com/search?q={query}&go=Submit&first={page_no}'
  417. self.engine_name = "Bing"
  418. self.MAX_DOMAINS = 30
  419. self.MAX_PAGES = 0
  420. enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent)
  421. self.q = q
  422. self.verbose = verbose
  423. return
  424.  
  425. def extract_domains(self, resp):
  426. links_list = list()
  427. link_regx = re.compile('<li class="b_algo"><h2><a href="(.*?)"')
  428. link_regx2 = re.compile('<div class="b_title"><h2><a href="(.*?)"')
  429. try:
  430. links = link_regx.findall(resp)
  431. links2 = link_regx2.findall(resp)
  432. links_list = links + links2
  433.  
  434. for link in links_list:
  435. link = re.sub('<(\/)?strong>|<span.*?>|<|>', '', link)
  436. if not link.startswith('http'):
  437. link = "http://" + link
  438. subdomain = urlparse.urlparse(link).netloc
  439. if subdomain not in self.subdomains and subdomain != self.domain:
  440. if self.verbose:
  441. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  442. self.subdomains.append(subdomain.strip())
  443. except Exception:
  444. pass
  445.  
  446. return links_list
  447.  
  448. def generate_query(self):
  449. if self.subdomains:
  450. fmt = 'domain:{domain} -www.{domain} -{found}'
  451. found = ' -'.join(self.subdomains[:self.MAX_DOMAINS])
  452. query = fmt.format(domain=self.domain, found=found)
  453. else:
  454. query = "domain:{domain} -www.{domain}".format(domain=self.domain)
  455. return query
  456.  
  457.  
  458. class BaiduEnum(enumratorBaseThreaded):
  459. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  460. subdomains = subdomains or []
  461. base_url = 'https://www.baidu.com/s?pn={page_no}&wd={query}&oq={query}'
  462. self.engine_name = "Baidu"
  463. self.MAX_DOMAINS = 2
  464. self.MAX_PAGES = 760
  465. enumratorBaseThreaded.__init__(self, base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  466. self.querydomain = self.domain
  467. self.q = q
  468. return
  469.  
  470. def extract_domains(self, resp):
  471. links = list()
  472. found_newdomain = False
  473. subdomain_list = []
  474. link_regx = re.compile('<a.*?class="c-showurl".*?>(.*?)</a>')
  475. try:
  476. links = link_regx.findall(resp)
  477. for link in links:
  478. link = re.sub('<.*?>|>|<|&nbsp;', '', link)
  479. if not link.startswith('http'):
  480. link = "http://" + link
  481. subdomain = urlparse.urlparse(link).netloc
  482. if subdomain.endswith(self.domain):
  483. subdomain_list.append(subdomain)
  484. if subdomain not in self.subdomains and subdomain != self.domain:
  485. found_newdomain = True
  486. if self.verbose:
  487. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  488. self.subdomains.append(subdomain.strip())
  489. except Exception:
  490. pass
  491. if not found_newdomain and subdomain_list:
  492. self.querydomain = self.findsubs(subdomain_list)
  493. return links
  494.  
  495. def findsubs(self, subdomains):
  496. count = Counter(subdomains)
  497. subdomain1 = max(count, key=count.get)
  498. count.pop(subdomain1, "None")
  499. subdomain2 = max(count, key=count.get) if count else ''
  500. return (subdomain1, subdomain2)
  501.  
  502. def check_response_errors(self, resp):
  503. return True
  504.  
  505. def should_sleep(self):
  506. time.sleep(random.randint(2, 5))
  507. return
  508.  
  509. def generate_query(self):
  510. if self.subdomains and self.querydomain != self.domain:
  511. found = ' -site:'.join(self.querydomain)
  512. query = "site:{domain} -site:www.{domain} -site:{found} ".format(domain=self.domain, found=found)
  513. else:
  514. query = "site:{domain} -site:www.{domain}".format(domain=self.domain)
  515. return query
  516.  
  517.  
  518. class NetcraftEnum(enumratorBaseThreaded):
  519. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  520. subdomains = subdomains or []
  521. self.base_url = 'https://searchdns.netcraft.com/?restriction=site+ends+with&host={domain}'
  522. self.engine_name = "Netcraft"
  523. self.lock = threading.Lock()
  524. super(NetcraftEnum, self).__init__(self.base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  525. self.q = q
  526. return
  527.  
  528. def req(self, url, cookies=None):
  529. cookies = cookies or {}
  530. try:
  531. resp = self.session.get(url, headers=self.headers, timeout=self.timeout, cookies=cookies)
  532. except Exception as e:
  533. self.print_(e)
  534. resp = None
  535. return resp
  536.  
  537. def get_next(self, resp):
  538. link_regx = re.compile('<A href="(.*?)"><b>Next page</b></a>')
  539. link = link_regx.findall(resp)
  540. link = re.sub('host=.*?%s' % self.domain, 'host=%s' % self.domain, link[0])
  541. url = 'http://searchdns.netcraft.com' + link
  542. return url
  543.  
  544. def create_cookies(self, cookie):
  545. cookies = dict()
  546. cookies_list = cookie[0:cookie.find(';')].split("=")
  547. cookies[cookies_list[0]] = cookies_list[1]
  548. cookies['netcraft_js_verification_response'] = hashlib.sha1(urllib.unquote(cookies_list[1])).hexdigest()
  549. return cookies
  550.  
  551. def get_cookies(self, headers):
  552. if 'set-cookie' in headers:
  553. cookies = self.create_cookies(headers['set-cookie'])
  554. else:
  555. cookies = {}
  556. return cookies
  557.  
  558. def enumerate(self):
  559. start_url = self.base_url.format(domain='example.com')
  560. resp = self.req(start_url)
  561. cookies = self.get_cookies(resp.headers)
  562. url = self.base_url.format(domain=self.domain)
  563. while True:
  564. resp = self.get_response(self.req(url, cookies))
  565. self.extract_domains(resp)
  566. if 'Next page' not in resp:
  567. return self.subdomains
  568. break
  569. url = self.get_next(resp)
  570.  
  571. def extract_domains(self, resp):
  572. links_list = list()
  573. link_regx = re.compile('<a href="http://toolbar.netcraft.com/site_report\?url=(.*)">')
  574. try:
  575. links_list = link_regx.findall(resp)
  576. for link in links_list:
  577. subdomain = urlparse.urlparse(link).netloc
  578. if not subdomain.endswith(self.domain):
  579. continue
  580. if subdomain and subdomain not in self.subdomains and subdomain != self.domain:
  581. if self.verbose:
  582. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  583. self.subdomains.append(subdomain.strip())
  584. except Exception:
  585. pass
  586. return links_list
  587.  
  588.  
  589. class DNSdumpster(enumratorBaseThreaded):
  590. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  591. subdomains = subdomains or []
  592. base_url = 'https://dnsdumpster.com/'
  593. self.live_subdomains = []
  594. self.engine_name = "DNSdumpster"
  595. self.threads = 70
  596. self.lock = threading.BoundedSemaphore(value=self.threads)
  597. self.q = q
  598. super(DNSdumpster, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  599. return
  600.  
  601. def check_host(self, host):
  602. is_valid = False
  603. Resolver = dns.resolver.Resolver()
  604. Resolver.nameservers = ['8.8.8.8', '8.8.4.4']
  605. self.lock.acquire()
  606. try:
  607. ip = Resolver.query(host, 'A')[0].to_text()
  608. if ip:
  609. if self.verbose:
  610. self.print_("%s%s: %s%s" % (R, self.engine_name, W, host))
  611. is_valid = True
  612. self.live_subdomains.append(host)
  613. except:
  614. pass
  615. self.lock.release()
  616. return is_valid
  617.  
  618. def req(self, req_method, url, params=None):
  619. params = params or {}
  620. headers = dict(self.headers)
  621. headers['Referer'] = 'https://dnsdumpster.com'
  622. try:
  623. if req_method == 'GET':
  624. resp = self.session.get(url, headers=headers, timeout=self.timeout)
  625. else:
  626. resp = self.session.post(url, data=params, headers=headers, timeout=self.timeout)
  627. except Exception as e:
  628. self.print_(e)
  629. resp = None
  630. return self.get_response(resp)
  631.  
  632. def get_csrftoken(self, resp):
  633. csrf_regex = re.compile("<input type='hidden' name='csrfmiddlewaretoken' value='(.*?)' />", re.S)
  634. token = csrf_regex.findall(resp)[0]
  635. return token.strip()
  636.  
  637. def enumerate(self):
  638. resp = self.req('GET', self.base_url)
  639. token = self.get_csrftoken(resp)
  640. params = {'csrfmiddlewaretoken': token, 'targetip': self.domain}
  641. post_resp = self.req('POST', self.base_url, params)
  642. self.extract_domains(post_resp)
  643. for subdomain in self.subdomains:
  644. t = threading.Thread(target=self.check_host, args=(subdomain,))
  645. t.start()
  646. t.join()
  647. return self.live_subdomains
  648.  
  649. def extract_domains(self, resp):
  650. tbl_regex = re.compile('<a name="hostanchor"><\/a>Host Records.*?<table.*?>(.*?)</table>', re.S)
  651. link_regex = re.compile('<td class="col-md-4">(.*?)<br>', re.S)
  652. links = []
  653. try:
  654. results_tbl = tbl_regex.findall(resp)[0]
  655. except IndexError:
  656. results_tbl = ''
  657. links_list = link_regex.findall(results_tbl)
  658. links = list(set(links_list))
  659. for link in links:
  660. subdomain = link.strip()
  661. if not subdomain.endswith(self.domain):
  662. continue
  663. if subdomain and subdomain not in self.subdomains and subdomain != self.domain:
  664. self.subdomains.append(subdomain.strip())
  665. return links
  666.  
  667.  
  668. class Virustotal(enumratorBaseThreaded):
  669. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  670. subdomains = subdomains or []
  671. base_url = 'https://www.virustotal.com/en/domain/{domain}/information/'
  672. self.engine_name = "Virustotal"
  673. self.lock = threading.Lock()
  674. self.q = q
  675. super(Virustotal, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  676. return
  677.  
  678. # the main send_req need to be rewritten
  679. def send_req(self, url):
  680. try:
  681. resp = self.session.get(url, headers=self.headers, timeout=self.timeout)
  682. except Exception as e:
  683. self.print_(e)
  684. resp = None
  685.  
  686. return self.get_response(resp)
  687.  
  688. # once the send_req is rewritten we don't need to call this function, the stock one should be ok
  689. def enumerate(self):
  690. url = self.base_url.format(domain=self.domain)
  691. resp = self.send_req(url)
  692. self.extract_domains(resp)
  693. return self.subdomains
  694.  
  695. def extract_domains(self, resp):
  696. link_regx = re.compile('<div class="enum.*?">.*?<a target="_blank" href=".*?">(.*?)</a>', re.S)
  697. try:
  698. links = link_regx.findall(resp)
  699. for link in links:
  700. subdomain = link.strip()
  701. if not subdomain.endswith(self.domain):
  702. continue
  703. if subdomain not in self.subdomains and subdomain != self.domain:
  704. if self.verbose:
  705. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  706. self.subdomains.append(subdomain.strip())
  707. except Exception:
  708. pass
  709.  
  710.  
  711. class ThreatCrowd(enumratorBaseThreaded):
  712. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  713. subdomains = subdomains or []
  714. base_url = 'https://www.threatcrowd.org/searchApi/v2/domain/report/?domain={domain}'
  715. self.engine_name = "ThreatCrowd"
  716. self.lock = threading.Lock()
  717. self.q = q
  718. super(ThreatCrowd, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  719. return
  720.  
  721. def req(self, url):
  722. try:
  723. resp = self.session.get(url, headers=self.headers, timeout=self.timeout)
  724. except Exception:
  725. resp = None
  726.  
  727. return self.get_response(resp)
  728.  
  729. def enumerate(self):
  730. url = self.base_url.format(domain=self.domain)
  731. resp = self.req(url)
  732. self.extract_domains(resp)
  733. return self.subdomains
  734.  
  735. def extract_domains(self, resp):
  736. try:
  737. links = json.loads(resp)['subdomains']
  738. for link in links:
  739. subdomain = link.strip()
  740. if not subdomain.endswith(self.domain):
  741. continue
  742. if subdomain not in self.subdomains and subdomain != self.domain:
  743. if self.verbose:
  744. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  745. self.subdomains.append(subdomain.strip())
  746. except Exception as e:
  747. pass
  748.  
  749.  
  750. class CrtSearch(enumratorBaseThreaded):
  751. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  752. subdomains = subdomains or []
  753. base_url = 'https://crt.sh/?q=%25.{domain}'
  754. self.engine_name = "SSL Certificates"
  755. self.lock = threading.Lock()
  756. self.q = q
  757. super(CrtSearch, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  758. return
  759.  
  760. def req(self, url):
  761. try:
  762. resp = self.session.get(url, headers=self.headers, timeout=self.timeout)
  763. except Exception:
  764. resp = None
  765.  
  766. return self.get_response(resp)
  767.  
  768. def enumerate(self):
  769. url = self.base_url.format(domain=self.domain)
  770. resp = self.req(url)
  771. if resp:
  772. self.extract_domains(resp)
  773. return self.subdomains
  774.  
  775. def extract_domains(self, resp):
  776. link_regx = re.compile('<TD>(.*?)</TD>')
  777. try:
  778. links = link_regx.findall(resp)
  779. for link in links:
  780. subdomain = link.strip()
  781. if not subdomain.endswith(self.domain) or '*' in subdomain:
  782. continue
  783.  
  784. if '@' in subdomain:
  785. subdomain = subdomain[subdomain.find('@')+1:]
  786.  
  787. if subdomain not in self.subdomains and subdomain != self.domain:
  788. if self.verbose:
  789. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  790. self.subdomains.append(subdomain.strip())
  791. except Exception as e:
  792. pass
  793.  
  794.  
  795. class PassiveDNS(enumratorBaseThreaded):
  796. def __init__(self, domain, subdomains=None, q=None, silent=False, verbose=True):
  797. subdomains = subdomains or []
  798. base_url = 'https://api.sublist3r.com/search.php?domain={domain}'
  799. self.engine_name = "PassiveDNS"
  800. self.lock = threading.Lock()
  801. self.q = q
  802. super(PassiveDNS, self).__init__(base_url, self.engine_name, domain, subdomains, q=q, silent=silent, verbose=verbose)
  803. return
  804.  
  805. def req(self, url):
  806. try:
  807. resp = self.session.get(url, headers=self.headers, timeout=self.timeout)
  808. except Exception as e:
  809. resp = None
  810.  
  811. return self.get_response(resp)
  812.  
  813. def enumerate(self):
  814. url = self.base_url.format(domain=self.domain)
  815. resp = self.req(url)
  816. if not resp:
  817. return self.subdomains
  818.  
  819. self.extract_domains(resp)
  820. return self.subdomains
  821.  
  822. def extract_domains(self, resp):
  823. try:
  824. subdomains = json.loads(resp)
  825. for subdomain in subdomains:
  826. if subdomain not in self.subdomains and subdomain != self.domain:
  827. if self.verbose:
  828. self.print_("%s%s: %s%s" % (R, self.engine_name, W, subdomain))
  829. self.subdomains.append(subdomain.strip())
  830. except Exception as e:
  831. pass
  832.  
  833.  
  834. class portscan():
  835. def __init__(self, subdomains, ports):
  836. self.subdomains = subdomains
  837. self.ports = ports
  838. self.threads = 20
  839. self.lock = threading.BoundedSemaphore(value=self.threads)
  840.  
  841. def port_scan(self, host, ports):
  842. openports = []
  843. self.lock.acquire()
  844. for port in ports:
  845. try:
  846. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  847. s.settimeout(2)
  848. result = s.connect_ex((host, int(port)))
  849. if result == 0:
  850. openports.append(port)
  851. s.close()
  852. except Exception:
  853. pass
  854. self.lock.release()
  855. if len(openports) > 0:
  856. print("%s%s%s - %sFound open ports:%s %s%s%s" % (G, host, W, R, W, Y, ', '.join(openports), W))
  857.  
  858. def run(self):
  859. for subdomain in self.subdomains:
  860. t = threading.Thread(target=self.port_scan, args=(subdomain, self.ports))
  861. t.start()
  862.  
  863.  
  864. def main(domain, threads, savefile, ports, silent, verbose, enable_bruteforce, engines):
  865. bruteforce_list = set()
  866. search_list = set()
  867.  
  868. if is_windows:
  869. subdomains_queue = list()
  870. else:
  871. subdomains_queue = multiprocessing.Manager().list()
  872.  
  873. # Check Bruteforce Status
  874. if enable_bruteforce or enable_bruteforce is None:
  875. enable_bruteforce = True
  876.  
  877. # Validate domain
  878. domain_check = re.compile("^(http|https)?[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,}$")
  879. if not domain_check.match(domain):
  880. if not silent:
  881. print(R + "Error: Please enter a valid domain" + W)
  882. return []
  883.  
  884. if not domain.startswith('http://') or not domain.startswith('https://'):
  885. domain = 'http://' + domain
  886.  
  887. parsed_domain = urlparse.urlparse(domain)
  888.  
  889. if not silent:
  890. print(B + "[-] Enumerating subdomains now for %s" % parsed_domain.netloc + W)
  891.  
  892. if verbose and not silent:
  893. print(Y + "[-] verbosity is enabled, will show the subdomains results in realtime" + W)
  894.  
  895. supported_engines = {'baidu': BaiduEnum,
  896. 'yahoo': YahooEnum,
  897. 'google': GoogleEnum,
  898. 'bing': BingEnum,
  899. 'ask': AskEnum,
  900. 'netcraft': NetcraftEnum,
  901. 'dnsdumpster': DNSdumpster,
  902. 'virustotal': Virustotal,
  903. 'threatcrowd': ThreatCrowd,
  904. 'ssl': CrtSearch,
  905. 'passivedns': PassiveDNS
  906. }
  907.  
  908. chosenEnums = []
  909.  
  910. if engines is None:
  911. chosenEnums = [
  912. BaiduEnum, YahooEnum, GoogleEnum, BingEnum, AskEnum,
  913. NetcraftEnum, DNSdumpster, Virustotal, ThreatCrowd,
  914. CrtSearch, PassiveDNS
  915. ]
  916. else:
  917. engines = engines.split(',')
  918. for engine in engines:
  919. if engine.lower() in supported_engines:
  920. chosenEnums.append(supported_engines[engine.lower()])
  921.  
  922. # Start the engines enumeration
  923. enums = [enum(domain, [], q=subdomains_queue, silent=silent, verbose=verbose) for enum in chosenEnums]
  924. for enum in enums:
  925. enum.start()
  926. for enum in enums:
  927. enum.join()
  928.  
  929. subdomains = set(subdomains_queue)
  930. for subdomain in subdomains:
  931. search_list.add(subdomain)
  932.  
  933. if enable_bruteforce:
  934. if not silent:
  935. print(G + "[-] Starting bruteforce module now using subbrute.." + W)
  936. record_type = False
  937. path_to_file = os.path.dirname(os.path.realpath(__file__))
  938. subs = os.path.join(path_to_file, 'subbrute', 'names.txt')
  939. resolvers = os.path.join(path_to_file, 'subbrute', 'resolvers.txt')
  940. process_count = threads
  941. output = False
  942. json_output = False
  943. bruteforce_list = subbrute.print_target(parsed_domain.netloc, record_type, subs, resolvers, process_count, output, json_output, search_list, verbose)
  944.  
  945. subdomains = search_list.union(bruteforce_list)
  946.  
  947. if subdomains:
  948. subdomains = sorted(subdomains, key=subdomain_sorting_key)
  949.  
  950. if savefile:
  951. write_file(savefile, subdomains)
  952.  
  953. if not silent:
  954. print(Y + "[-] Total Unique Subdomains Found: %s" % len(subdomains) + W)
  955.  
  956. if ports:
  957. if not silent:
  958. print(G + "[-] Start port scan now for the following ports: %s%s" % (Y, ports) + W)
  959. ports = ports.split(',')
  960. pscan = portscan(subdomains, ports)
  961. pscan.run()
  962.  
  963. elif not silent:
  964. for subdomain in subdomains:
  965. print(G + subdomain + W)
  966. return subdomains
  967.  
  968.  
  969. if __name__ == "__main__":
  970. args = parse_args()
  971. domain = args.domain
  972. threads = args.threads
  973. savefile = args.output
  974. ports = args.ports
  975. enable_bruteforce = args.bruteforce
  976. verbose = args.verbose
  977. engines = args.engines
  978. if verbose or verbose is None:
  979. verbose = True
  980. banner()
  981. res = main(domain, threads, savefile, ports, silent=False, verbose=verbose, enable_bruteforce=enable_bruteforce, engines=engines)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement