def test_is_authorized_for_function(self): instance = ESAPI.access_controller() auth = ESAPI.authenticator() auth.current_user = auth.get_user("ACAlice") self.assertTrue(instance.is_authorized_for_function("/FunctionA")) self.assertFalse(instance.is_authorized_for_function("/FunctionAdeny")) self.assertFalse(instance.is_authorized_for_function("/FunctionB")) self.assertFalse(instance.is_authorized_for_function("/FunctionBdeny")) self.assertTrue(instance.is_authorized_for_function("/FunctionC")) self.assertFalse(instance.is_authorized_for_function("/FunctionCdeny")) auth.current_user = auth.get_user("ACBob") self.assertFalse(instance.is_authorized_for_function("/FunctionA")) self.assertFalse(instance.is_authorized_for_function("/FunctionAdeny")) self.assertTrue(instance.is_authorized_for_function("/FunctionB")) self.assertFalse(instance.is_authorized_for_function("/FunctionBdeny")) self.assertTrue(instance.is_authorized_for_function("/FunctionD")) self.assertFalse(instance.is_authorized_for_function("/FunctionDdeny")) auth.current_user = auth.get_user("ACMitch") self.assertTrue(instance.is_authorized_for_function("/FunctionA")) self.assertFalse(instance.is_authorized_for_function("/FunctionAdeny")) self.assertTrue(instance.is_authorized_for_function("/FunctionB")) self.assertFalse(instance.is_authorized_for_function("/FunctionBdeny")) self.assertTrue(instance.is_authorized_for_function("/FunctionC")) self.assertFalse(instance.is_authorized_for_function("/FunctionCdeny")) instance.assert_authorized_for_function("/FunctionA") self.assertRaises(AccessControlException, instance.assert_authorized_for_function, "/FunctionDdeny" )
def add_event(self, event_name, log_message): self.logger.warning( Logger.SECURITY_FAILURE, _("Security event %(name)s received: %(message)s") % { 'name': event_name, 'message': log_message, }) # Add the event to the current user, which may trigger a detector user = ESAPI.authenticator().current_user try: self.add_security_event(user, "event_" + event_name) except IntrusionException, extra: quota = ESAPI.security_configuration().get_quota("event_" + event_name) for action in quota.actions: message = (_( "User exceeded quota of %(count)s per %(interval)s seconds for event %(event_name)s. Taking actions %(actions)s" ) % { 'count': quota.count, 'interval': quota.interval, 'event_name': event_name, 'actions': quota.actions, }) self.take_security_action(action, message)
def test_is_authorized_for_service(self): instance = ESAPI.access_controller() auth = ESAPI.authenticator() auth.current_user = auth.get_user("ACAlice") self.assertTrue(instance.is_authorized_for_service("/services/ServiceA")) self.assertFalse(instance.is_authorized_for_service("/services/ServiceB")) self.assertTrue(instance.is_authorized_for_service("/services/ServiceC")) self.assertFalse(instance.is_authorized_for_service("/test/ridiculous")) auth.current_user = auth.get_user("ACBob") self.assertFalse(instance.is_authorized_for_service("/services/ServiceA")) self.assertTrue(instance.is_authorized_for_service("/services/ServiceB")) self.assertFalse(instance.is_authorized_for_service("/services/ServiceF")) self.assertFalse(instance.is_authorized_for_service("/test/ridiculous")) auth.current_user = auth.get_user("ACMitch") self.assertTrue(instance.is_authorized_for_service("/services/ServiceA")) self.assertTrue(instance.is_authorized_for_service("/services/ServiceB")) self.assertFalse(instance.is_authorized_for_service("/services/ServiceE")) self.assertFalse(instance.is_authorized_for_service("/test/ridiculous")) instance.assert_authorized_for_service("/services/ServiceD") self.assertRaises(AccessControlException, instance.assert_authorized_for_service, "/test/ridiculous" )
def add_exception(self, exception): # Log the exception if hasattr(exception, 'get_log_message'): self.logger.warning( Logger.SECURITY_FAILURE, exception.get_log_message(), exception ) else: self.logger.warning( Logger.SECURITY_FAILURE, exception.message, exception ) if isinstance(exception, IntrusionException): return # Add the exception to the current user, which may trigger a # dector user = ESAPI.authenticator().current_user event_name = exception.__class__.__name__ try: self.add_security_event(user, event_name) except IntrusionException, extra: quota = ESAPI.security_configuration().get_quota(event_name) for action in quota.actions: message = (_("User exceeded quota of %(count)s per %(interval)s seconds for event %(event_name)s. Taking actions %(actions)s") % {'count' : quota.count, 'interval' : quota.interval, 'event_name' : event_name, 'actions' : quota.actions,}) self.take_security_action(action, message)
def add_exception(self, exception): # Log the exception if hasattr(exception, 'get_log_message'): self.logger.warning(Logger.SECURITY_FAILURE, exception.get_log_message(), exception) else: self.logger.warning(Logger.SECURITY_FAILURE, exception.message, exception) if isinstance(exception, IntrusionException): return # Add the exception to the current user, which may trigger a # dector user = ESAPI.authenticator().current_user event_name = exception.__class__.__name__ try: self.add_security_event(user, event_name) except IntrusionException, extra: quota = ESAPI.security_configuration().get_quota(event_name) for action in quota.actions: message = (_( "User exceeded quota of %(count)s per %(interval)s seconds for event %(event_name)s. Taking actions %(actions)s" ) % { 'count': quota.count, 'interval': quota.interval, 'event_name': event_name, 'actions': quota.actions, }) self.take_security_action(action, message)
def add_cookie(self, response=None, **kwargs): if response is None: response = self.current_response if not kwargs.has_key('secure'): if ESAPI.security_configuration().get_force_secure_cookies(): kwargs['secure'] = True if not kwargs.has_key('httponly'): if ESAPI.security_configuration().get_force_http_only_cookies(): kwargs['httponly'] = True # Validate the key and value errors = ValidationErrorList() safe_key = ESAPI.validator().get_valid_input("cookie name", kwargs['key'], "HTTPCookieName", 50, False, errors) safe_value = ESAPI.validator().get_valid_input("cookie value", kwargs['value'], "HTTPCookieValue", 5000, False, errors) kwargs['key'] = safe_key kwargs['value'] = safe_value # If no errors, set the cookie if len(errors) == 0: response.set_cookie(**kwargs) return # Error! self.logger.warning( Logger.SECURITY_FAILURE, _("Attempt to add unsafe data to cookie (skip mode). Skipping cookie and continuing.") )
def set_remember_token(self, password, max_age, domain, path, request=None, response=None): if request is None: request = self.current_request if response is None: response = self.current_response user = ESAPI.authenticator().current_user try: self.kill_cookie(self.REMEMBER_TOKEN_COOKIE_NAME, request, response) # Seal already contains random data clear_token = user.account_name + "|" + password expiry = datetime.now() + timedelta(seconds=max_age) crypt_token = ESAPI.encryptor().seal(clear_token, expiry) morsel = Cookie.Morsel() morsel.value = crypt_token morsel['max-age'] = max_age morsel['domain'] = domain morsel['path'] = path response.cookies[self.REMEMBER_TOKEN_COOKIE_NAME] = morsel self.logger.info( Logger.SECURITY_SUCCESS, _("Enabled remember me token for %(user)s") % {'user' : user.account_name} ) return crypt_token except IntegrityException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Attempt to set remember me token failed for %(user)s") % {'user' : user.account_name}, extra )
def validate_roles(self, roles): """ Checks that the roles passed in contain only letters, numbers, and underscores. Also checks that roles are no more than 10 characters long. If a role does not pass validation, it is not included in the list of roles returned by this method. A log warning is also generated for any invalid roles. @param roles: the list of roles to validate according to the criteria stated above. @return: a list of roles that are valid according to the criteria stated above. """ ret = [] for role in roles: canonical = '' try: stripped = role.strip() canonical = ESAPI.encoder().canonicalize(stripped) except EncodingException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Failed to canonicalize role: %(role)s") % {'role': stripped}, extra) if not ESAPI.validator().is_valid_input( "Roles in FileBasedAccessController", canonical, "AccessControlRule", 200, False): self.logger.warning( Logger.SECURITY_FAILURE, _("Role is invalid, and was not added to the list of roles for this rule: %(role)s" ) % {'role': stripped}) else: ret.append(stripped)
def validate_roles(self, roles): """ Checks that the roles passed in contain only letters, numbers, and underscores. Also checks that roles are no more than 10 characters long. If a role does not pass validation, it is not included in the list of roles returned by this method. A log warning is also generated for any invalid roles. @param roles: the list of roles to validate according to the criteria stated above. @return: a list of roles that are valid according to the criteria stated above. """ ret = [] for role in roles: canonical = '' try: stripped = role.strip() canonical = ESAPI.encoder().canonicalize(stripped) except EncodingException, extra: self.logger.warning( Logger.SECURITY_FAILURE, _("Failed to canonicalize role: %(role)s") % {'role' : stripped}, extra ) if not ESAPI.validator().is_valid_input( "Roles in FileBasedAccessController", canonical, "AccessControlRule", 200, False ): self.logger.warning( Logger.SECURITY_FAILURE, _("Role is invalid, and was not added to the list of roles for this rule: %(role)s") % {'role' : stripped} ) else:
def log(self, level, event_type, message, exception=None): """ Log the message after optionally encoding any special characters that might be dangerous when viewed by an HTML based log viewer. Also encode any carriage returns and line feeds to prevent log injection attacks. This logs all the supplied parameters plus the user ID, user's source IP, a logging specific session ID, and the current date/time. It will only log the message if the current logging level is enabled, otherwise it will discard the message. @param level: the severity level of the security event @param event_type: the event_type of the event (SECURITY, FUNCTIONALITY, etc.) @param message: the message @param exception: an exception """ # Before we waste all kinds of time preparing this event for the # log, let check to see if its loggable if not self.pyLogger.isEnabledFor(level): return user = ESAPI.authenticator().current_user # create a random session number for the user to represent the # user's 'session', if it doesn't exist already sid = _("unknown") request = ESAPI.http_utilities().current_request if request is not None: session = request.session if session is not None: sid = session.get('ESAPI_SESSION', None) # if there is no session id for the user yet, create one # and store it in the user's session if sid is None: sid = str(ESAPI.randomizer().get_random_integer(0, 1000000)) session['ESAPI_SESSION'] = sid # ensure there's something to log if message is None: message = "" # ensure no CRLF injection into logs for forging records clean = message.replace('\n', '_').replace('\r', '_') if ESAPI.security_configuration().get_log_encoding_required(): clean = ESAPI.encoder().encode_for_html(message) if message != clean: clean += " (Encoded)" extra = { 'eventType' : str(event_type), 'eventSuccess' : [_("SUCCESS"),_("FAILURE")][event_type.is_success()], 'user' : user.account_name, 'hostname' : user.last_host_address, 'sessionID' : sid, } self.pyLogger.log(level, clean, extra=extra)
def test_is_valid_dir_path(self): encoder_class = ESAPI.security_configuration().get_class_for_interface('encoder') validator_class = ESAPI.security_configuration().get_class_for_interface('validator') encoder = encoder_class([HTMLEntityCodec()]) instance = validator_class(encoder) if os.name == 'nt': # Windows # Windows paths that don't exist and thus should fail self.assertFalse(instance.is_valid_directory_path("test", "c:\\ridiculous", "c:\\", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\jeff", "c:\\", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\temp\\..\\etc", "c:\\", False)) # When the parent directory doesn't exist, these should fail self.assertFalse(instance.is_valid_directory_path("test", "c:\\", "c:\\ridiculous", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\", None, False)) # Windows paths that should pass self.assertTrue(instance.is_valid_directory_path("test", "C:\\", "C:\\", False)) # Windows root directory self.assertTrue(instance.is_valid_directory_path("test", "C:\\Windows", "C:\\", False)) # Windows always exist directory # Should fail for files self.assertFalse(instance.is_valid_directory_path("test", "C:\\Windows\\System32\\cmd.exe", "C:\\", False)) # Windows command shell # Testing case insensitivity between input and parent_dir self.assertTrue(instance.is_valid_directory_path("test", "C:\\", "c:\\", False)) # Windows root directory self.assertTrue(instance.is_valid_directory_path("test", "c:\\Windows", "C:\\", False)) # Windows always exist directory # Testing the verification of the parent directory self.assertFalse(instance.is_valid_directory_path("test", "c:\\", "C:\\windows", False)) # Windows always exist directory self.assertFalse(instance.is_valid_directory_path("test", "C:\\", "C:\\windows", False)) # Windows always exist directory # Unix specific paths should not pass self.assertFalse(instance.is_valid_directory_path("test", "/tmp", "/", False)) # Unix Temporary directory self.assertFalse(instance.is_valid_directory_path("test", "/bin/sh", "/", False)) # Unix Standard shell self.assertFalse(instance.is_valid_directory_path("test", "/etc/config", "/", False)) # Unix specific paths that should not exist or work self.assertFalse(instance.is_valid_directory_path("test", "/etc/ridiculous", "/", False)) self.assertFalse(instance.is_valid_directory_path("test", "/tmp/../etc", "/", False)) else: # Windows paths should fail self.assertFalse(instance.is_valid_directory_path("test", "c:\\ridiculous", "c:\\", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\temp\\..\\etc", "c:\\", False)) # Standard Windows locations should fail self.assertFalse(instance.is_valid_directory_path("test", "c:\\", "c:\\", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\Windows\\temp", "c:\\", False)) self.assertFalse(instance.is_valid_directory_path("test", "c:\\Windows\\System32\\cmd.exe", "c:\\", False)) # Unix specific paths should pass # Root self.assertTrue(instance.is_valid_directory_path("test", "/", "/", False)) # /bin self.assertTrue(instance.is_valid_directory_path("test", "/bin", "/", False)) # Unix specific paths that should not exist or work self.assertFalse(instance.is_valid_directory_path("test", "/etc/ridiculous", "/", False)) self.assertFalse(instance.is_valid_directory_path("test", "/tmp/../etc", "/", False))
def test_encode_for_base64(self): instance = ESAPI.encoder() self.assertEquals(None, instance.encode_for_base64(None)) self.assertEquals(None, instance.decode_from_base64(None)) for i in range(100): random_string = ESAPI.randomizer().get_random_string( 20, Encoder.CHAR_SPECIALS ) encoded = instance.encode_for_base64( random_string ) decoded = instance.decode_from_base64( encoded ) self.assertEquals( random_string, decoded )
def __init__(self): Encryptor.__init__(self) self.logger = ESAPI.logger("DefaultEncryptor") # Hashing self.hash_algorithm = ESAPI.security_configuration().get_hash_algorithm() self.hash_iterations = ESAPI.security_configuration().get_hash_iterations() # Encryption self.encrypt_algorithm = ESAPI.security_configuration().get_encryption_algorithm() if self.encrypt_algorithm not in self.VALID_ENCRYPTION_ALGOS: raise EncryptionException( _("Encryption Failure - Unknown algorithm for encryption: %(algorithm)s") % {'algorithm' : self.encrypt_algorithm} ) self.encryption_key_length = ESAPI.security_configuration().get_encryption_key_length() self.master_salt = ESAPI.security_configuration().get_master_salt() # Public key crypto self.signing_algorithm = ESAPI.security_configuration().get_digital_signature_algorithm() if self.signing_algorithm not in self.VALID_SIGNING_ALGOS: raise EncryptionException( _("Failure to encrypt"), _("Encryption Failure - Unknown algorithm for signing: %(algorithm)s") % {'algorithm' : self.signing_algorithm} ) self.signing_key_length = ESAPI.security_configuration().get_digital_signature_key_length() # Key locations self.keys_location = os.path.realpath(ESAPI.security_configuration().get_encryption_keys_location()) + '/' self.keys_symmetric_location = self.keys_location + "symmetric" self.keys_asymmetric_private_location = self.keys_location + "asymmetric-private" self.keys_asymmetric_public_location = self.keys_location + "asymmetric-public"
def test_add_exception(self): ESAPI.intrusion_detector().add_exception(RuntimeError('message')) ESAPI.intrusion_detector().add_exception( ValidationException("user message", "log message")) ESAPI.intrusion_detector().add_exception( IntrusionException("user message", "log message")) username = "******" password = "******" auth = ESAPI.authenticator() user = auth.create_user(username, password, password) user.enable() request = MockHttpRequest() response = MockHttpResponse() ESAPI.http_utilities().set_current_http(request, response) user.login_with_password(password) # Generate some exceptions to disable the account for i in range(15): IntegrityException("IntegrityException %s" % i, "IntegrityException %s" % i) self.assertFalse(user.is_logged_in()) self.assertTrue(user.is_locked())
def test_add_exception(self): ESAPI.intrusion_detector().add_exception( RuntimeError('message') ) ESAPI.intrusion_detector().add_exception( ValidationException("user message", "log message") ) ESAPI.intrusion_detector().add_exception( IntrusionException("user message", "log message") ) username = "******" password = "******" auth = ESAPI.authenticator() user = auth.create_user(username, password, password) user.enable() request = MockHttpRequest() response = MockHttpResponse() ESAPI.http_utilities().set_current_http(request, response) user.login_with_password(password) # Generate some exceptions to disable the account for i in range(15): IntegrityException( "IntegrityException %s" % i, "IntegrityException %s" % i ) self.assertFalse(user.is_logged_in()) self.assertTrue(user.is_locked())
def test_is_authorized_for_data(self): instance = ESAPI.access_controller() auth = ESAPI.authenticator() adminR = "java.util.ArrayList" adminRW = "java.lang.Math" userW = "java.util.Date" userRW = "java.lang.String" anyR = "java.io.BufferedReader" userAdminR = "java.util.Random" userAdminRW = "java.awt.event.MouseWheelEvent" undefined = "java.io.FileWriter" # test User auth.current_user = auth.get_user("ACAlice") self.assertTrue(instance.is_authorized_for_data("read", userRW)) self.assertFalse(instance.is_authorized_for_data("read", undefined)) self.assertFalse(instance.is_authorized_for_data("write", undefined)) self.assertFalse(instance.is_authorized_for_data("read", userW)) self.assertFalse(instance.is_authorized_for_data("read", adminRW)) self.assertTrue(instance.is_authorized_for_data("write", userRW)) self.assertTrue(instance.is_authorized_for_data("write", userW)) self.assertFalse(instance.is_authorized_for_data("write", anyR)) self.assertTrue(instance.is_authorized_for_data("read", anyR)) self.assertTrue(instance.is_authorized_for_data("read", userAdminR)) self.assertTrue(instance.is_authorized_for_data("write", userAdminRW)) # test Admin auth.current_user = auth.get_user("ACBob") self.assertTrue(instance.is_authorized_for_data("read", adminRW)) self.assertFalse(instance.is_authorized_for_data("read", undefined)) self.assertFalse(instance.is_authorized_for_data("write", undefined)) self.assertFalse(instance.is_authorized_for_data("read", userRW)) self.assertTrue(instance.is_authorized_for_data("write", adminRW)) self.assertFalse(instance.is_authorized_for_data("write", anyR)) self.assertTrue(instance.is_authorized_for_data("read", anyR)) self.assertTrue(instance.is_authorized_for_data("read", userAdminR)) self.assertTrue(instance.is_authorized_for_data("write", userAdminRW)) # test User/Admin auth.current_user = auth.get_user("ACMitch") self.assertTrue(instance.is_authorized_for_data("read", userRW)) self.assertFalse(instance.is_authorized_for_data("read", undefined)) self.assertFalse(instance.is_authorized_for_data("write", undefined)) self.assertFalse(instance.is_authorized_for_data("read", userW)) self.assertTrue(instance.is_authorized_for_data("read", adminR)) self.assertTrue(instance.is_authorized_for_data("write", userRW)) self.assertTrue(instance.is_authorized_for_data("write", userW)) self.assertFalse(instance.is_authorized_for_data("write", anyR)) self.assertTrue(instance.is_authorized_for_data("read", anyR)) self.assertTrue(instance.is_authorized_for_data("read", userAdminR)) self.assertTrue(instance.is_authorized_for_data("write", userAdminRW)) instance.assert_authorized_for_data("read", userRW) self.assertRaises(AccessControlException, instance.assert_authorized_for_data, "write", adminR )
def set_header(self, name, value, response=None): if response is None: response = self.current_response try: safe_name = ESAPI.validator().get_valid_input("setHeader", name.strip(), "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input("setHeader", value.strip(), "HTTPHeaderValue", 500, False) response[safe_name] = safe_value except ValidationException, extra: self.logger( Logger.SECURITY_FAILURE, _("Attempt to set invalid header denied"), extra )
def test_add_csrf_token(self): instance = ESAPI.authenticator() username = "******" password = '******' user = instance.create_user(username, password, password) instance.current_user = user csrf1 = ESAPI.http_utilities().add_csrf_token('/test1') self.assertTrue(csrf1.find('?') > -1) csrf2 = ESAPI.http_utilities().add_csrf_token('test1?one=two') self.assertTrue(csrf2.find('?') > -1)
def test_save_too_long_state_in_cookie(self): request = MockHttpRequest() response = MockHttpResponse() ESAPI.http_utilities().set_current_http(request, response) foo = "abcd" * 1000 data = {'long': foo} try: ESAPI.http_utilities().encrypt_state_in_cookie(response, data) self.fail() except: pass
def set_header(self, name, value, response=None): if response is None: response = self.current_response try: safe_name = ESAPI.validator().get_valid_input( "setHeader", name.strip(), "HTTPHeaderName", 20, False) safe_value = ESAPI.validator().get_valid_input( "setHeader", value.strip(), "HTTPHeaderValue", 500, False) response[safe_name] = safe_value except ValidationException, extra: self.logger(Logger.SECURITY_FAILURE, _("Attempt to set invalid header denied"), extra)
def test_decode_from_base64(self): instance = ESAPI.encoder() for i in range(100): random_string = ESAPI.randomizer().get_random_string( 20, Encoder.CHAR_SPECIALS ) encoded = instance.encode_for_base64( random_string ) decoded = instance.decode_from_base64( encoded ) self.assertEqual( random_string, decoded ) for i in range(100): random_string = ESAPI.randomizer().get_random_string( 20, Encoder.CHAR_SPECIALS ) encoded = ESAPI.randomizer().get_random_string(1, Encoder.CHAR_ALPHANUMERICS) + instance.encode_for_base64( random_string ) decoded = instance.decode_from_base64( encoded ) self.assertFalse( random_string == decoded )
def test_crypt(self): instance = ESAPI.encryptor() def check(plaintext): ciphertext = instance.encrypt(plaintext) result = instance.decrypt(ciphertext) self.assertEquals(plaintext, result) # Example plaintext check("test1234") # 20 random strings for i in range(20): check(ESAPI.randomizer().get_random_string(40, Encoder.CHAR_ALPHANUMERICS))
def test_set_no_cache_headers(self): request = MockHttpRequest() response = MockHttpResponse() ESAPI.http_utilities().set_current_http(request, response) self.assertEquals(0, len(response.headers)) response.headers["test1"] = "1" response.headers["test2"] = "2" response.headers["test3"] = "3" self.assertEquals(3, len(response.headers)) ESAPI.http_utilities().set_no_cache_headers( response ) self.assertTrue(response.headers.has_key('Cache-Control')) self.assertTrue(response.headers.has_key('Expires'))
def test_crypt(self): instance = ESAPI.encryptor() def check(plaintext): ciphertext = instance.encrypt(plaintext) result = instance.decrypt(ciphertext) self.assertEquals(plaintext, result) # Example plaintext check("test1234") # 20 random strings for i in range(20): check(ESAPI.randomizer().get_random_string( 40, Encoder.CHAR_ALPHANUMERICS))
def test_state_from_encrypted_cookie(self): request = MockHttpRequest() response = MockHttpResponse() empty = ESAPI.http_utilities().decrypt_state_from_cookie(request) self.assertEquals({}, empty) m = {'one' : 'aspect', 'two' : 'ridiculous', 'test_hard' : "&(@#*!^|;,." } ESAPI.http_utilities().encrypt_state_in_cookie(m, response) value = response.headers['Set-Cookie'] encrypted = value[value.find('=')+1:value.find(';')] ESAPI.encryptor().decrypt(encrypted)
def test_change_session_identifier(self): request = MockHttpRequest() response = MockHttpResponse() ESAPI.http_utilities().set_current_http(request, response) session = request.session session['one'] = 'one' session['two'] = 'two' session['three'] = 'three' id1 = request.session.id session = ESAPI.http_utilities().change_session_identifier(request) id2 = request.session.id self.assertFalse(id1 == id2) self.assertEquals("one", session['one'])
def test_sign_and_verify(self): instance = ESAPI.encryptor() def check(plaintext): sig = instance.sign(plaintext) self.assertTrue( instance.verify_signature(sig, plaintext) ) self.assertFalse( instance.verify_signature(sig, "ridiculous") ) self.assertFalse( instance.verify_signature("ridiculous", plaintext) ) # Example plaintext check("test1234") # 20 random strings for i in range(20): check(ESAPI.randomizer().get_random_string(40, Encoder.CHAR_ALPHANUMERICS))
def test_set_remember_token(self): instance = ESAPI.authenticator() account_name = "joestheplumber" password = instance.generate_strong_password() user = instance.create_user(account_name, password, password) user.enable() request = MockHttpRequest() request.POST['username'] = account_name request.POST['password'] = password response = MockHttpResponse() instance.login(request, response) max_age = 60 * 60 * 24 * 14 ESAPI.http_utilities().set_remember_token( password, max_age, "domain", '/', request, response )
def encrypt_cc(self, cc_number): """ Encrypt credit card number for safe storage. """ # Generate last_4 self.last_4 = cc_number[-4:] # Encrypt instance = ESAPI.encryptor() self.encrypted_number = instance.encrypt(cc_number)
def test_query_to_dict(self): instance = ESAPI.http_utilities() query = '?a=1&b=2&c=3' testing = instance.query_to_dict(query) correct = {'a' : '1', 'b' : '2', 'c' : '3'} self.assertEquals(testing, correct)
def test_add_header(self): instance = ESAPI.http_utilities() request = MockHttpRequest() response = MockHttpResponse() instance.set_current_http(request, response) instance.add_header('HeaderName', 'HeaderValue')
def __init__(self): self.logger = ESAPI.logger("Executor") self.working_dir = ESAPI.security_configuration().get_working_directory() self.max_running_time = ESAPI.security_configuration().get_max_running_time() if os.name == "nt": self.logger.warning( Logger.SECURITY_SUCCESS, _("Using WindowsCodec for Executor. If this is not running on Windows, this could allow for injection"), ) self.codec = WindowsCodec() else: self.logger.warning( Logger.SECURITY_SUCCESS, _("Using UnixCodec for Executor. If this is not running on Unix, this could allow injection"), ) self.codec = UnixCodec()
def test_is_valid_cc(self): instance = ESAPI.validator() self.assertTrue(instance.is_valid_credit_card("cctest1", "1234 9876 0000 0008", False)) self.assertTrue(instance.is_valid_credit_card("cctest2", "1234987600000008", False)) self.assertFalse(instance.is_valid_credit_card("cctest3", "12349876000000081", False)) self.assertFalse(instance.is_valid_credit_card("cctest4", "4417 1234 5678 9112", False))
def test_is_valid_number(self): instance = ESAPI.validator() # testing negative range self.assertFalse(instance.is_valid_number("test", int, "-4", 1, 10, False)) self.assertTrue(instance.is_valid_number("test", int, "-4", -10, 10, False)) # testing null value self.assertTrue(instance.is_valid_number("test", int, None, -10, 10, True)) self.assertFalse(instance.is_valid_number("test", int, None, -10, 10, False)) # testing empty string self.assertTrue(instance.is_valid_number("test", int, "", -10, 10, True)) self.assertFalse(instance.is_valid_number("test", int, "", -10, 10, False)) # testing improper range self.assertFalse(instance.is_valid_number("test", int, "5", 10, -10, False)) # testing non-integers self.assertTrue(instance.is_valid_number("test", float, "4.3214", -10, 10, True)) self.assertTrue(instance.is_valid_number("test", float, "-1.65", -10, 10, True)) # other testing self.assertTrue(instance.is_valid_number("test", int, "4", 1, 10, False)) self.assertTrue(instance.is_valid_number("test", int, "400", 1, 10000, False)) self.assertTrue(instance.is_valid_number("test", int, "400000000", 1, 400000000, False)) self.assertFalse(instance.is_valid_number("test", int, "4000000000000", 1, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "alsdkf", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "--10", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "14.1414234x", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "Infinity", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "-Infinity", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "NaN", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "-NaN", 10, 10000, False)) self.assertFalse(instance.is_valid_number("test", int, "+NaN", 10, 10000, False))
def test_encode_for_xml_attribute(self): instance = ESAPI.encoder() self.assertEquals(None, instance.encode_for_xml_attribute(None)) self.assertEquals(" ", instance.encode_for_xml_attribute(" ")) self.assertEquals("<script>", instance.encode_for_xml_attribute("<script>")) self.assertEquals(",.-_", instance.encode_for_xml_attribute(",.-_")) self.assertEquals(" !@$%()=+{}[]", instance.encode_for_xml_attribute(" !@$%()=+{}[]"))
def get_cc_rule(self, encoder): pattern = ESAPI.security_configuration().get_validation_pattern( "CreditCard") ccr = StringValidationRule("ccrule", encoder, pattern) ccr.set_maximum_length(CC_MAX_LENGTH) ccr.set_allow_none(False) return ccr
def test_create_user(self): instance = ESAPI.authenticator() account_name = "awesomebob" password = "******" user = instance.create_user(account_name, password, password) # duplicate user self.assertRaises(AuthenticationException, instance.create_user, account_name, password, password) # passwords don't match self.assertRaises(AuthenticationException, instance.create_user, "nonmatchuser", "a1b2c3d4e5f6g7h8", "z1b2c3d4e5f6g7h8") # Weak password self.assertRaises(AuthenticationException, instance.create_user, "weakuser", "weak1", "weak1") # None username self.assertRaises(AuthenticationException, instance.create_user, None, "comPl3xPass", "comPl3xPass") # None password self.assertRaises(AuthenticationException, instance.create_user, "nopassword", None, None)
def test_get_user(self): instance = ESAPI.authenticator() account_name = "testGetUser" password = "******" instance.create_user(account_name, password, password) self.assertTrue( instance.get_user(account_name) ) self.assertFalse( instance.get_user("ridiculous") )
def test_change_password(self): instance = ESAPI.authenticator() old_password = '******' user = self.create_test_user(password=old_password) print (_("Hash of %(old_password)s = %(hash)s") % {'old_password' : old_password, 'hash' : instance.get_hashed_password(user)}) password1 = "SomethingElse34#$" user.change_password(old_password, password1, password1) print (_("Hash of %(password)s = %(hash)s") % {'password' : password1, 'hash' : instance.get_hashed_password(user)}) self.assertTrue(user.verify_password(password1)) self.assertFalse(user.verify_password(old_password)) password2 = "YetAnother56%^" user.change_password(password1, password2, password2) print (_("Hash of %(password)s = %(hash)s") % {'password' : password2, 'hash' : instance.get_hashed_password(user)}) self.assertTrue(user.verify_password(password2)) self.assertFalse(user.verify_password(password1)) try: user.change_password(password2, password1, password1) # Should not be able to re-use a password self.fail() except AuthenticationException: pass self.assertFalse(user.verify_password("badpass"))
def test_unix_codec(self): instance = ESAPI.encoder() unix = UnixCodec() immune = '' self.assertEquals(None, instance.encode_for_os(unix, None)) npbs = PushbackString("n") self.assertEquals(None, unix.decode_character(npbs)) c = '<' cpbs = PushbackString(unix.encode_character(immune, c)) decoded = unix.decode_character(cpbs) self.assertEquals(c, decoded) epbs = PushbackString("") self.assertEquals(None, unix.decode_character(epbs)) orig = "/etc/passwd" enc = unix.encode(immune, orig) self.assertEquals(orig, unix.decode(enc)) self.assertEquals(orig, unix.decode(orig)) self.assertEquals("c\\:\\\\jeff", instance.encode_for_os(unix, "c:\\jeff")) self.assertEquals("c\\:\\\\jeff", unix.encode(immune, "c:\\jeff")) self.assertEquals("dir\\ \\&\\ foo", instance.encode_for_os(unix, "dir & foo")) self.assertEquals("dir\\ \\&\\ foo", unix.encode(immune, "dir & foo")) # Unix paths (that must be encoded safely) self.assertEquals("\\/etc\\/hosts", instance.encode_for_os(unix, "/etc/hosts")) self.assertEquals("\\/etc\\/hosts\\;\\ ls\\ -l", instance.encode_for_os(unix, "/etc/hosts; ls -l")) self.assertEquals("\\", unix.decode('\\')) self.assertEquals(unichr(12345), unix.encode('', unichr(12345)))
def test_hash_password(self): instance = ESAPI.authenticator() username = "******" password = "******" result1 = instance.hash_password(password, username) result2 = instance.hash_password(password, username) self.assertEquals(result1, result2)
def test_execute_on_windows(self): if os.name != 'nt': print "Not executing test_execute_on_windows because os.name != 'nt'" return codec = WindowsCodec() instance = ESAPI.executor() orig_executable = "C:\\Windows\System32\cmd.exe" parent_dir = 'C:\\' params = ['/C', 'dir'] result = instance.execute_system_command(orig_executable, params, parent_dir, codec=codec) print "result:", result executable = orig_executable + ";inject.exe" self.assertRaises(ExecutorException, instance.execute_system_command, executable, params, parent_dir, codec=codec) executable = orig_executable + "\\..\\cmd.exe" self.assertRaises(ExecutorException, instance.execute_system_command, executable, params, parent_dir, codec=codec) work_dir = "C:\\ridiculous" self.assertRaises(ExecutorException, instance.execute_system_command, orig_executable, params, parent_dir, work_dir, codec=codec) params.append("&dir") result = instance.execute_system_command(orig_executable, params, parent_dir, codec=codec) print "result:", result params = params[:-1] + ['c:\\autoexec.bat'] result = instance.execute_system_command(orig_executable, params, parent_dir, codec=codec) print "result:", result params = params[:-1] + ['c:\\autoexec.bat c:\\config.sys'] result = instance.execute_system_command(orig_executable, params, parent_dir, codec=codec) print "result:", result
def hash(self, plaintext, salt, iterations=None): # Verify a MasterSalt has been set if not self.master_salt or len(self.master_salt) < 20: raise Exception( _("There is an error in the application configuration. The MasterSalt has not been set properly. Please see the instructions in the README for setting up a crypto keyring. Currently, Encryptor_MasterSalt=%(value)s" ) % {'value': self.master_salt}) if iterations is None: iterations = self.hash_iterations try: digest = hashlib.new(self.hash_algorithm) digest.update(self.master_salt) digest.update(salt) digest.update(plaintext) bytes = digest.digest() for i in range(self.hash_iterations): digest = hashlib.new(self.hash_algorithm) digest.update(bytes) bytes = digest.digest() encoded = ESAPI.encoder().encode_for_base64(bytes) return encoded except ValueError, e: raise EncryptionException( _("Problem hashing"), _("Internal Error - Can't find hash algorithm ") + self.hash_algorithm)
def is_session_timeout(self): session = ESAPI.http_utilities().current_request.session if session is None: return True deadline = session.last_accessed_time + self.IDLE_TIMEOUT_LENGTH return datetime.now() > deadline
def test_windows_codec(self): instance = ESAPI.encoder() win = WindowsCodec() immune = [] self.assertEquals(None, instance.encode_for_os(win, None)) npbs = PushbackString("n") self.assertEquals(None, win.decode_character(npbs)) epbs = PushbackString("") self.assertEquals(None, win.decode_character(epbs)) c = '<' cpbs = PushbackString(win.encode_character(immune, c)) decoded = win.decode_character(cpbs) self.assertEquals(c, decoded) orig = "c:\\jeff" enc = win.encode(Encoder.CHAR_ALPHANUMERICS, orig) self.assertEquals(orig, win.decode(enc)) self.assertEquals(orig, win.decode(orig)) self.assertEquals("c^:^\\jeff", instance.encode_for_os(win, "c:\\jeff")); self.assertEquals("c^:^\\jeff", win.encode(immune, "c:\\jeff")) self.assertEquals("dir^ ^&^ foo", instance.encode_for_os(win, "dir & foo")) self.assertEquals("dir^ ^&^ foo", win.encode(immune, "dir & foo"))
def __init__(self, codecs=None): """ Instantiates a new DefaultEncoder. @param codecs: : a list of codec instances to use for canonicalization """ Encoder.__init__(self) self.html_codec = HTMLEntityCodec() self.percent_codec = PercentCodec() self.javascript_codec = JavascriptCodec() self.vbscript_codec = VBScriptCodec() self.css_codec = CSSCodec() self.ldap_codec = LDAPCodec() self.ldap_dn_codec = LDAPDNCodec() self.logger = ESAPI.logger("Encoder") # Used for canonicalization self.codecs = [] if codecs is None: self.codecs.append(self.html_codec) self.codecs.append(self.percent_codec) self.codecs.append(self.javascript_codec) # Leaving out css_codec because it eats / characters # Leaving out vbscript_codec because it eats " characters else: for codec in codecs: if not isinstance(codec, Codec): raise TypeError( _("Codecs in list must be instances of children of Codec" )) self.codecs.append(codec)