def test_soap_authentication_with_past_created_value( self, target, port, uri, adm_user, adm_password, minutes): token = UsernameToken(username=adm_user, password=adm_password, use_digest=True, created=datetime.datetime.utcnow() - datetime.timedelta(minutes=minutes)) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post('http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.info( 'Request from the past is rejected (Connection aborted)') else: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code == 400 or rsp.status_code == 401: logger.info( 'Request from the past is rejected ({} minutes delay)'. format(minutes)) else: logger.critical( 'Request from the past is accepted ({} minutes delay)'. format(minutes)) assert False
def test_authentication_bypass_ldap_injection_soap(self, target, port, uri, adm_user): for i in self.ldap_injections: user = adm_user + i token = UsernameToken(username=user, password='', use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post('http://{host}:{port}{uri}'.format( host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code == 200: logger.critical( 'Authentication bypass by LDAP injection at SOAP level: {}' .format(user)) assert False logger.info( 'No authentication bypass by LDAP injection at SOAP level found')
def test_weak_authentication_methods_soap_passwordtext_auth( self, target, port, uri, adm_user, adm_password): token = UsernameToken(username=adm_user, password=adm_password, use_digest=False) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post('http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.info('Exception during request: Connection aborted') else: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code == 400 or rsp.status_code == 401: logger.info('SOAP PasswordText authentication rejected') elif rsp.status_code == 200: logger.critical('SOAP PasswordText authentication accepted') assert False
def _send_requests(self, target, port, uri, user, password, n): """ Send a n POST requests to http://target:port/uri with SOAP authentication and calculate the average of response time :param target: IP address :param port: Port number :param uri: URI :param user: User for the SOAP authentication :param password: Password for the SOAP authentication :param n: Number of requests to send :return: Average of response time """ token = UsernameToken(username=user, password=password, use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) average = datetime.timedelta() for i in range(n): try: rsp = requests.post('http://{host}:{port}{uri}'.format( host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: logger.error('Exception during request:\n{}'.format(e)) assert False else: average += rsp.elapsed return average / n
def test_replay_attack_soap_level(self, target, port, uri, adm_user, adm_password, delay): token = UsernameToken(username=adm_user, password=adm_password, use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post('http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code != 200: logger.error( 'Unexpected return code {} during first request (SOAP auth)' .format(rsp.status_code)) assert False else: try: time.sleep(delay) rsp = requests.post( 'http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.info( 'Replay attack stopped at SOAP level (Connection aborted)' ) else: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code == 200: logger.critical( 'Replay attack successful at SOAP level (delay={}s)' .format(delay)) assert False elif rsp.status_code == 400 or rsp.status_code == 401: logger.info( 'Replay attack stopped at SOAP level (delay={}s)'. format(delay)) else: logger.error( 'Unexpected return code {} when replay at SOAP level' .format(rsp.status_code)) assert False
def try_login_soap(n): i = 1 while i <= n: token = UsernameToken(username=adm_user, password=adm_password + 'bad', use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post( 'http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] != 'Connection aborted.': logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code != 400: logger.error( 'Receive unexpected {} status code (SOAP auth)'. format(rsp.status_code)) assert False i += 1 token = UsernameToken(username=adm_user, password=adm_password, use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp = requests.post('http://{host}:{port}{uri}'.format( host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.critical( 'Account locked out after {} SOAP login attempt (Connection aborted)' .format(i)) assert False else: logger.error('Exception during request:\n{}'.format(e)) assert False else: if rsp.status_code != 200: logger.critical( 'Account locked out after {} SOAP login attempt (code {})' .format(i, rsp.status_code))
def test_username_enumeration_response_content(self, target, port, uri, adm_user, adm_password): token = UsernameToken(username=adm_user, password=adm_password + 'bad', use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp_bad_password = requests.post( 'http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.info('Exception during request: Connection aborted') rsp_bad_password = None else: logger.error('Exception during request:\n{}'.format(e)) assert False token = UsernameToken(username=adm_user + 'bad', password=adm_password, use_digest=True) message = etree.fromstring(self.GetUsers) token.apply(message, message[0]) try: rsp_bad_username = requests.post( 'http://{host}:{port}{uri}'.format(host=target, port=port, uri=uri), etree.tostring(message).decode('utf-8'), headers=self.base_headers, timeout=30) except Exception as e: if e.args[0].args[0] == 'Connection aborted.': logger.info('Exception during request: Connection aborted') rsp_bad_username = None else: logger.error('Exception during request:\n{}'.format(e)) assert False if (rsp_bad_password is None and rsp_bad_username is not None) or \ (rsp_bad_password is not None and rsp_bad_username is None): logger.critical( 'Username enumeration possible: differences found between responses to a bad password and ' 'a bad username') assert False if rsp_bad_username.status_code != rsp_bad_password.status_code: logger.critical( 'Username enumeration possible: differences found between responses status code to a bad ' 'password and a bad username') assert False if rsp_bad_password.content != rsp_bad_username.content: logger.critical( 'Username enumeration possible: differences found between responses content to a bad ' 'password and a bad username') assert False logger.info('Username enumeration not possible regarding responses')