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)
Exemple #2
0
 def test_encode_for_xml_attribute(self):
     instance = ESAPI.encoder()
     self.assertEquals(None, instance.encode_for_xml_attribute(None))
     self.assertEquals("&#x20;", instance.encode_for_xml_attribute(" "))
     self.assertEquals("&lt;script&gt;", instance.encode_for_xml_attribute("<script>"))
     self.assertEquals(",.-_", instance.encode_for_xml_attribute(",.-_"))
     self.assertEquals("&#x20;&#x21;&#x40;&#x24;&#x25;&#x28;&#x29;&#x3d;&#x2b;&#x7b;&#x7d;&#x5b;&#x5d;", instance.encode_for_xml_attribute(" !@$%()=+{}[]"))
Exemple #3
0
    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 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 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 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  
             )
Exemple #7
0
    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 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) 
Exemple #9
0
    def __init__(self, encoder=None):
        Validator.__init__(self)
        if encoder:
            self.encoder = encoder
        else:
            self.encoder = ESAPI.encoder()

        self.make_file_validator()
 def encrypt_state_in_cookie(self, cleartext_map, response=None):
     if response is None:
         response = self.current_response
         
     buf = ''
     for key, value in cleartext_map.items():
         if buf != '':
             buf += '&'
     
         try:
             key = ESAPI.encoder().encode_for_url( key )
             value = ESAPI.encoder().encode_for_url( value )
             buf += "%s=%s" % (key, value)
         except EncodingException, extra:
             self.logger.error( Logger.SECURITY_FAILURE,
                 _("Problem encrypting state in cookie - skipping entry"),
                 extra=extra )
 def __init__(self, encoder=None):
     Validator.__init__(self)
     if encoder:
         self.encoder = encoder
     else:
         self.encoder = ESAPI.encoder()
         
     self.make_file_validator()
    def gen_keys(self):
        """
        Create new keys.
        """
        print(
            _("Creating new keys in %(location)s") %
            {'location': self.keys_location})

        # Create symmetric key
        os.makedirs(self.keys_symmetric_location)
        keyczartool.main([
            'create',
            "--location=%s" % self.keys_symmetric_location, "--purpose=crypt"
        ])
        keyczartool.main([
            'addkey',
            "--location=%s" % self.keys_symmetric_location, "--status=primary",
            "--size=%s" % self.encryption_key_length
        ])

        # Create asymmetric private keys for signing
        os.makedirs(self.keys_asymmetric_private_location)
        keyczartool.main([
            'create',
            "--location=%s" % self.keys_asymmetric_private_location,
            "--purpose=sign",
            "--asymmetric=%s" % self.encrypt_algorithm
        ])
        keyczartool.main([
            'addkey',
            "--location=%s" % self.keys_asymmetric_private_location,
            "--status=primary",
            "--size=%s" % self.signing_key_length
        ])

        # Extract public keys for signing
        os.makedirs(self.keys_asymmetric_public_location)
        keyczartool.main([
            'create',
            "--location=%s" % self.keys_asymmetric_public_location,
            "--purpose=sign",
            "--asymmetric=%s" % self.encrypt_algorithm
        ])
        keyczartool.main([
            'pubkey',
            "--location=%s" % self.keys_asymmetric_private_location,
            "--status=primary",
            "--destination=%s" % self.keys_asymmetric_public_location
        ])

        # Gen a new master salt
        from os import urandom
        salt = urandom(20)
        print "Please modify this line in esapi/conf/settings.py:"
        print "Encryptor_MasterSalt = '" + ESAPI.encoder().encode_for_base64(
            salt) + "'"

        print "Done!"
Exemple #13
0
    def encrypt_state_in_cookie(self, cleartext_map, response=None):
        if response is None:
            response = self.current_response

        buf = ''
        for key, value in cleartext_map.items():
            if buf != '':
                buf += '&'

            try:
                key = ESAPI.encoder().encode_for_url(key)
                value = ESAPI.encoder().encode_for_url(value)
                buf += "%s=%s" % (key, value)
            except EncodingException, extra:
                self.logger.error(
                    Logger.SECURITY_FAILURE,
                    _("Problem encrypting state in cookie - skipping entry"),
                    extra=extra)
Exemple #14
0
 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 )
Exemple #15
0
 def test_encode_for_dn(self):
     instance = ESAPI.encoder()
     self.assertEquals(None, instance.encode_for_dn(None))
     self.assertEquals("Hello�", instance.encode_for_dn("Hello�"), "No special characters to escape")
     self.assertEquals("\\# Hello�", instance.encode_for_dn("# Hello�"), "leading #")
     self.assertEquals("\\ Hello�", instance.encode_for_dn(" Hello�"), "leading space")
     self.assertEquals("Hello�\\ ", instance.encode_for_dn("Hello� "), "trailing space")
     self.assertEquals("Hello\\<\\>", instance.encode_for_dn("Hello<>"), "less than greater than")
     self.assertEquals("\\  \\ ", instance.encode_for_dn("   "), "only 3 spaces")
     self.assertEquals("\\ Hello\\\\ \\+ \\, \\\"World\\\" \\;\\ ", instance.encode_for_dn(" Hello\\ + , \"World\" ; "), "Christmas Tree DN")
Exemple #16
0
    def __init__(self, type_name, encoder=None):
        self.type_name = None
        self.allow_none = False
        self.encoder = None

        if encoder:
            self.set_encoder(encoder)
        else:
            self.set_encoder(ESAPI.encoder())

        self.set_type_name(type_name)
 def __init__(self, type_name, encoder=None):
     self.type_name = None
     self.allow_none = False
     self.encoder = None
 
     if encoder:
         self.set_encoder( encoder )
     else:
         self.set_encoder( ESAPI.encoder() )
     
     self.set_type_name(type_name)
 def gen_keys(self):
     """
     Create new keys.
     """
     print (_("Creating new keys in %(location)s") % 
         {'location' : self.keys_location} )
         
     # Create symmetric key
     os.makedirs(self.keys_symmetric_location)
     keyczartool.main(
         ['create', 
          "--location=%s" % self.keys_symmetric_location,
          "--purpose=crypt"] )
     keyczartool.main(
         ['addkey', 
          "--location=%s" % self.keys_symmetric_location,
          "--status=primary",
          "--size=%s" % self.encryption_key_length] )
          
     # Create asymmetric private keys for signing
     os.makedirs(self.keys_asymmetric_private_location)
     keyczartool.main(
         ['create', 
          "--location=%s" % self.keys_asymmetric_private_location,
          "--purpose=sign",
          "--asymmetric=%s" % self.encrypt_algorithm] )
     keyczartool.main(
         ['addkey', 
          "--location=%s" % self.keys_asymmetric_private_location,
          "--status=primary",
          "--size=%s" % self.signing_key_length] )
          
     # Extract public keys for signing
     os.makedirs(self.keys_asymmetric_public_location)
     keyczartool.main(
         ['create', 
          "--location=%s" % self.keys_asymmetric_public_location,
          "--purpose=sign",
          "--asymmetric=%s" % self.encrypt_algorithm] )
     keyczartool.main(
         ['pubkey', 
          "--location=%s" % self.keys_asymmetric_private_location,
          "--status=primary",
          "--destination=%s" % self.keys_asymmetric_public_location] )
          
     # Gen a new master salt
     from os import urandom
     salt = urandom(20)
     print "Please modify this line in esapi/conf/settings.py:"
     print "Encryptor_MasterSalt = '" + ESAPI.encoder().encode_for_base64(salt) + "'"
          
     print "Done!"
Exemple #19
0
    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 )
Exemple #20
0
    def test_percent_codec(self):
        instance = ESAPI.encoder()
        
        ### High level
        self.assertEquals(None, instance.encode_for_url(None))
        self.assertEquals("%3Cscript%3E", instance.encode_for_url("<script>"))
        self.assertEquals("%03", instance.encode_for_url(unichr(3)))
        self.assertEquals("+", instance.encode_for_url(" "))
        self.assertEquals(unichr(12345), instance.encode_for_url(unichr(12345)))
        
        self.assertEquals(None, instance.decode_from_url(None))
        self.assertEquals("<script>", instance.decode_from_url("%3Cscript%3E"))
        self.assertEquals(unichr(3), instance.decode_from_url("%03"))
        self.assertEquals("     ", instance.decode_from_url("+++++") )
        self.assertEquals(unichr(12345), instance.decode_from_url(unichr(12345)))

        # Wrap in assertRaises
        self.assertEquals("%3xridiculous", instance.decode_from_url( "%3xridiculous" ))
Exemple #21
0
 def test_codec_for_javascript(self):
     instance = ESAPI.encoder()
     
     ### High level
     self.assertEquals(None, instance.encode_for_javascript(None))
     self.assertEquals("\\x3Cscript\\x3E", instance.encode_for_javascript("<script>"))
     self.assertEquals(",.\\x2D_\\x20", instance.encode_for_javascript(",.-_ "))
     self.assertEquals("\\x21\\x40\\x24\\x25\\x28\\x29\\x3D\\x2B\\x7B\\x7D\\x5B\\x5D", instance.encode_for_javascript("!@$%()=+{}[]"))
     
     #   Unicode
     self.assertEquals(unichr(12345), instance.encode_for_javascript(unichr(12345)))
     
     ### Low level
     codec = JavascriptCodec()
     
     # Bad hex format
     self.assertEquals("\\xAQ", codec.decode("\\xAQ"))
     self.assertEquals("\\uAAQ", codec.decode("\\uAAQ"))
Exemple #22
0
    def test_html_codec(self):
        instance = ESAPI.encoder()
        
        ### High level
        
        self.assertEquals(None, instance.encode_for_html(None))
        # test invalid characters are replaced with spaces
        self.assertEquals("a b c d e f&#x9;g", instance.encode_for_html("a" + unichr(0) + "b" + unichr(4) + "c" + unichr(128) + "d" + unichr(150) + "e" +unichr(159) + "f" + unichr(9) + "g"))
        
        self.assertEquals("&lt;script&gt;", instance.encode_for_html("<script>"))
        self.assertEquals("&amp;lt&#x3b;script&amp;gt&#x3b;", instance.encode_for_html("&lt;script&gt;"))
        self.assertEquals("&#x21;&#x40;&#x24;&#x25;&#x28;&#x29;&#x3d;&#x2b;&#x7b;&#x7d;&#x5b;&#x5d;", instance.encode_for_html("!@$%()=+{}[]"))

        self.assertEquals(",.-_ ", instance.encode_for_html(",.-_ "))
        self.assertEquals("dir&amp;", instance.encode_for_html("dir&"))
        self.assertEquals("one&amp;two", instance.encode_for_html("one&two"))
        # Unicode
        self.assertEquals(unichr(12345), instance.encode_for_html(unichr(12345)))
        
        ### Low lovel
        codec = HTMLEntityCodec()
        
        cases = (
                 # PLAIN - ENCODED - ALT_ENCODINGS
                 ('', '', ()),
                 ('t','t', ()),
                 ('test', 'test', ()),
                 ('<script>', '&lt;script&gt;', ()),
                 ('!@#$%^&*(){}[]?+/=|\\', '&#x21;&#x40;&#x23;&#x24;&#x25;&#x5e;&amp;&#x2a;&#x28;&#x29;&#x7b;&#x7d;&#x5b;&#x5d;&#x3f;&#x2b;&#x2f;&#x3d;&#x7c;&#x5c;', ()),
                 ('"`~1234_-', '&quot;&#x60;&#x7e;1234&#x5f;&#x2d;', ()),
                 (unichr(9), "&#x9;", ()),
                 (unichr(12345), unichr(12345), ()),
                 ('\\', '&#x5c;', ()),
             )
             
        for case in cases:
            self.assertEquals(case[ENCODED], codec.encode('', case[PLAIN]))
            self.assertEquals(case[PLAIN], codec.decode(case[ENCODED]))
            for encoding in case[ALT_ENCODINGS]:
                self.assertEquals(case[PLAIN], codec.decode(encoding))
        
        # Bad entity name
        self.assertEquals("&ridiculous;", codec.decode("&ridiculous;"))
Exemple #23
0
    def test_codec_for_vbscript(self):
        instance = ESAPI.encoder()
        
        ### High level
        self.assertEquals(None, instance.encode_for_vbscript(None))
        self.assertEquals( "chrw(60)&\"script\"&chrw(62)", instance.encode_for_vbscript("<script>"))
        self.assertEquals( "x\"&chrw(32)&chrw(33)&chrw(64)&chrw(36)&chrw(37)&chrw(40)&chrw(41)&chrw(61)&chrw(43)&chrw(123)&chrw(125)&chrw(91)&chrw(93)", instance.encode_for_vbscript("x !@$%()=+{}[]"))
        self.assertEquals( "alert\"&chrw(40)&chrw(39)&\"ESAPI\"&chrw(32)&\"test\"&chrw(33)&chrw(39)&chrw(41)", instance.encode_for_vbscript("alert('ESAPI test!')" ))
        self.assertEquals( "jeff.williams\"&chrw(64)&\"aspectsecurity.com", instance.encode_for_vbscript("*****@*****.**"))
        self.assertEquals( "test\"&chrw(32)&chrw(60)&chrw(62)&chrw(32)&\"test", instance.encode_for_vbscript("test <> test" ))
        
        ### Low level
        codec = VBScriptCodec()

        cases = (
             # PLAIN - ENCODED - ALT_ENCODINGS
             ('', '', ()), # 0 length string
             ('t','t', ()),
             ('test', 'test', ()),
             (unichr(12345), unichr(12345), ()),
         )
             
        for case in cases:
            if case[ENCODED] is not None:
                self.assertEquals(case[ENCODED], codec.encode('', case[PLAIN]))
                self.assertEquals(case[PLAIN], codec.decode(case[ENCODED]))
            for encoding in case[ALT_ENCODINGS]:
                print "encoding=",encoding
                self.assertEquals(case[PLAIN], codec.decode(encoding))
                
        encode_only_cases = (
             # PLAIN - ENCODED - ALT_ENCODINGS
             ('<script>', 'chrw(60)&"script"&chrw(62)', ()),
             ('!@#$%^&*(){}[]?+/=|\\', 'chrw(33)&chrw(64)&chrw(35)&chrw(36)&chrw(37)&chrw(94)&chrw(38)&chrw(42)&chrw(40)&chrw(41)&chrw(123)&chrw(125)&chrw(91)&chrw(93)&chrw(63)&chrw(43)&chrw(47)&chrw(61)&chrw(124)&chrw(92)', ()),
             ('"`~1234_-', 'chrw(34)&chrw(96)&chrw(126)&"1234"&chrw(95)&chrw(45)', ()),
             (unichr(9), "chrw(9)", ()),
             ('\\', 'chrw(92)', ('\\')),
         )
         
        for case in encode_only_cases:
            if case[ENCODED] is not None:
                self.assertEquals(case[ENCODED], codec.encode('', case[PLAIN]))
 def search_for_rule(self, dictionary, roles, key):
     """
     Search for the rule. Four mapping rules are used in order:
     
         - Exact match, e.g. /access/login
         - Longest path prefix match, beginning / and ending /*, e.g. /access/* or /*
         - Extension matching, beginning *., e.g. *.css
         - Default rule, specified by the single character pattern
         
     @param dictionary: the map containing the access rules
     @param roles: a list of roles the user has
     @param key: the file, url, object, etc. being checked for access
     @return: the rule stating whether to allow or deny access
     """
     canonical = None
     try:
         canonical = ESAPI.encoder().canonicalize(key)
     except EncodingException, extra:
         self.logger.warning(
             Logger.SECURITY_FAILURE, False,
             _("Failed to canonicalize input: %(key)s") % {'key': key})
 
 def search_for_rule(self, dictionary, roles, key):
     """
     Search for the rule. Four mapping rules are used in order:
     
         - Exact match, e.g. /access/login
         - Longest path prefix match, beginning / and ending /*, e.g. /access/* or /*
         - Extension matching, beginning *., e.g. *.css
         - Default rule, specified by the single character pattern
         
     @param dictionary: the map containing the access rules
     @param roles: a list of roles the user has
     @param key: the file, url, object, etc. being checked for access
     @return: the rule stating whether to allow or deny access
     """
     canonical = None
     try:
         canonical = ESAPI.encoder().canonicalize(key)
     except EncodingException, extra:
         self.logger.warning( Logger.SECURITY_FAILURE, False,
             _("Failed to canonicalize input: %(key)s") %
Exemple #26
0
    def test_sql_codec(self):
        instance = ESAPI.encoder()

        ### High level
        mySQL1 = MySQLCodec( MySQLCodec.ANSI_MODE )
        self.assertEquals(None, instance.encode_for_sql(mySQL1, None))
        self.assertEquals("Jeff'' or ''1''=''1", instance.encode_for_sql(mySQL1, "Jeff' or '1'='1"))
        self.assertEquals("''", instance.encode_for_sql(mySQL1, "'"))
        self.assertEquals(unichr(12345), instance.encode_for_sql(mySQL1, unichr(12345)))
        
        mySQL2 = MySQLCodec( MySQLCodec.MYSQL_MODE )
        self.assertEquals(None, instance.encode_for_sql(mySQL2, None))
        self.assertEquals("Jeff\\' or \\'1\\'\\=\\'1", instance.encode_for_sql(mySQL2, "Jeff' or '1'='1"))
        self.assertEquals("\\t", instance.encode_for_sql(mySQL2, unichr(9)))
        self.assertEquals(unichr(12345), instance.encode_for_sql(mySQL2, unichr(12345)))
    
        ### Low level
        cases = ('test',
                 '<script>',
                 'the answer',
                 '!@#$%^&*(){}[]?+/=|\\',
                 '"`~1234_-',
                 unichr(9),
                 unichr(12345))
                 
        for case in cases:
            self.assertEquals(case, mySQL1.decode(mySQL1.encode('', case)))
            self.assertEquals(case, mySQL2.decode(mySQL1.encode('', case)))
            
        self.assertEquals(unichr(9), mySQL2.decode("\\t"))
        self.assertEquals('m', mySQL2.decode("\\m"))
        
        self.assertEquals("'", mySQL1.decode("''"))
        self.assertEquals("'", mySQL1.decode("'"))
        self.assertEquals("'q", mySQL1.decode("'q"))
        
        # Bad mode
        self.assertRaises(BadModeError, MySQLCodec, -2 )
Exemple #27
0
    def test_double_encoding_canonicalization(self):
        instance = ESAPI.encoder()
        
        # note these examples use the strict=False flag on canonicalize to allow
        # full decoding without throwing an IntrusionException. Generally, you
        # should use strict mode as allowing double-encoding is an abomination.
        
        # double encoding examples
        self.assertEquals( "<", instance.canonicalize("&#x26;lt&#59", False )); #double entity
        self.assertEquals( "\\", instance.canonicalize("%255c", False)); #double percent
        self.assertEquals( "%", instance.canonicalize("%2525", False)); #double percent
        
        # double encoding with multiple schemes example
        self.assertEquals( "<", instance.canonicalize("%26lt%3b", False)); #first entity, then percent
        self.assertEquals( "&", instance.canonicalize("&#x25;26", False)); #first percent, then entity
          
        # nested encoding examples
        self.assertEquals( "<", instance.canonicalize("%253c", False)); #nested encode % with percent
        self.assertEquals( "<", instance.canonicalize("%%33%63", False)); #nested encode both nibbles with percent
        self.assertEquals( "<", instance.canonicalize("%%33c", False)); # nested encode first nibble with percent
        self.assertEquals( "<", instance.canonicalize("%3%63", False));  #nested encode second nibble with percent
        self.assertEquals( "<", instance.canonicalize("&&#108;t;", False)); #nested encode l with entity
        self.assertEquals( "<", instance.canonicalize("%2&#x35;3c", False)); #triple percent, percent, 5 with entity
        
        # nested encoding with multiple schemes examples
        self.assertEquals( "<", instance.canonicalize("&%6ct;", False)); # nested encode l with percent
        self.assertEquals( "<", instance.canonicalize("%&#x33;c", False)); #nested encode 3 with entity            
        
        # multiple encoding tests
        self.assertEquals( "% & <script> <script>", instance.canonicalize( "%25 %2526 %26#X3c;script&#x3e; &#37;3Cscript%25252525253e", False ) )
        self.assertEquals( "< < < < < < <", instance.canonicalize( "%26lt; %26lt; &#X25;3c &#x25;3c %2526lt%253B %2526lt%253B %2526lt%253B", False ) )

        # test strict mode with both mixed and multiple encoding
        self.assertRaises( IntrusionException, instance.canonicalize, "%26lt; %26lt; &#X25;3c &#x25;3c %2526lt%253B %2526lt%253B %2526lt%253B" )
        self.assertRaises( IntrusionException, instance.canonicalize, "%253Cscript" ) 
        self.assertRaises( IntrusionException, instance.canonicalize, "&#37;3Cscript" )
Exemple #28
0
 def test_codec_for_css(self):
     instance = ESAPI.encoder()
    
     ### High level
     self.assertEquals(None, instance.encode_for_css(None))
     self.assertEquals("\\3c script\\3e ", instance.encode_for_css("<script>"))
     self.assertEquals("\\21 \\40 \\24 \\25 \\28 \\29 \\3d \\2b \\7b \\7d \\5b \\5d ", instance.encode_for_css("!@$%()=+{}[]"))
     # Unicode
     self.assertEquals(unichr(12345), instance.encode_for_css(unichr(12345)))
     
     ### Low level
     codec = CSSCodec()
     
     cases = (
          # PLAIN - ENCODED - ALT_ENCODINGS
          ('', '', ()), # 0 length string
          ('t','t', ()),
          ('test', 'test', ()),
          ('<script>', '\\3c script\\3e ', ()),
          ('!@#$%^&*(){}[]?+/=|\\', '\\21 \\40 \\23 \\24 \\25 \\5e \\26 \\2a \\28 \\29 \\7b \\7d \\5b \\5d \\3f \\2b \\2f \\3d \\7c \\5c ', ()),
          ('"`~1234_-', '\\22 \\60 \\7e 1234\\5f \\2d ', ()),
          (unichr(9), "\\9 ", ()),
          (unichr(12345), unichr(12345), ()),
          ('\\', '\\5c ', ('\\')),
          ('\\2aq', None, ("\\2aq",)), # Malformed hex
          ('\\2aq ', None, ("\\2aq ",)), # Malformed hex
          ('\\q ', None, ('\\q ',)), # Malformed hex
      )
          
     for case in cases:
         if case[ENCODED] is not None:
             self.assertEquals(case[ENCODED], codec.encode('', case[PLAIN]))
             self.assertEquals(case[PLAIN], codec.decode(case[ENCODED]))
         for encoding in case[ALT_ENCODINGS]:
             print "encoding=",encoding
             self.assertEquals(case[PLAIN], codec.decode(encoding))
Exemple #29
0
 def test_oracle_codec(self):
     instance = ESAPI.encoder()
     ### High level
     oracle = OracleCodec()
     self.assertEquals(None, instance.encode_for_sql(oracle, None))
     self.assertEquals("''", instance.encode_for_sql(oracle, "'"))
     
     
     ### Low level
     cases = ('t',
              'test',
              '<script>',
              'the answer',
              '!@#$%^&*(){}[]?+/=|\\',
              '"`~1234_-',
              unichr(9),
              unichr(12345),
              '\\')
              
     for case in cases:
         self.assertEquals(case, oracle.decode(oracle.encode('', case)))
         
     self.assertEquals("''", oracle.encode('', "'"))
     self.assertEquals("'", oracle.decode("''"))
    def execute_system_command(self,
                               executable,
                               params,
                               parent_dir,
                               working_dir=None,
                               codec=None,
                               log_params=True):

        if codec is None:
            codec = self.codec

        if working_dir is None:
            working_dir = self.working_dir

        try:
            # Executable must exist
            if not os.path.exists(executable):
                raise ExecutorException(
                    _("Execution failure"),
                    _("No such executable: %(executable)s") %
                    {'executable': executable})

            directory, filename = os.path.split(executable)

            # executable must use canonical path
            if not ESAPI.validator().is_valid_directory_path(
                    "Executor", directory, parent_dir, False):
                raise ExecutorException(
                    _("Execution failure"),
                    _("Directory did not pass validation: %(dir)s") %
                    {'dir': directory})

            # Must be in approved list
            approved = ESAPI.security_configuration().get_allowed_executables()
            if executable not in approved:
                raise ExecutorException(
                    _("Execution failure"),
                    _("Attempt to invoke executable that is not listed as an approved executable in configuration: %(executable)s"
                      ) % {'executable': executable})

            # Escape parameters
            params = [
                ESAPI.encoder().encode_for_os(codec, param) for param in params
            ]

            # Working directory must exist
            if not os.path.exists(working_dir):
                raise ExecutorException(
                    _("Execution failure"),
                    _("No such working directory for running executable: %(dir)s"
                      ) % {'dir': working_dir})

            args = params
            args.insert(0, executable)
            start_time = datetime.now()
            proc = subprocess.Popen(args,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT,
                                    cwd=working_dir)

            if log_params:
                self.logger.warning(
                    Logger.SECURITY_SUCCESS,
                    _("Initiating executable %(args)s in %(dir)s") % {
                        'args': str(args),
                        'dir': working_dir
                    })
            else:
                self.logger.warning(
                    Logger.SECURITY_SUCCESS,
                    _("Initiating executable %(executable)s in %(dir)s") % {
                        'executable': args[0],
                        'dir': working_dir
                    })

            while (proc.poll() is None
                   and datetime.now() - start_time < self.max_running_time):
                time.sleep(1)

            if proc.poll() is None:
                # Kill the process because it ran too long
                proc.terminate()
                time.sleep(1)
                if proc.poll() is None:
                    proc.kill()
                raise ExecutorException(
                    _("Execution failure"),
                    _("Process exceeded maximum running time and was killed: %(executable)s"
                      ) % {'executable': executable})

            else:
                # Process terminated in allotted timeframe
                stdout_and_err = proc.communicate()
                return stdout_and_err
        except Exception, extra:
            raise ExecutorException(
                _("Execution failure"),
                _("Exception thrown during execution of system command"),
                extra)
Exemple #31
0
 def test_encode_for_xpath(self):
     instance = ESAPI.encoder()
     self.assertEquals(None, instance.encode_for_xpath(None))
     self.assertEquals("&#x27;or 1&#x3d;1", instance.encode_for_xpath("'or 1=1"))
 def get_master_salt(self):
     return ESAPI.encoder().decode_from_base64(settings.Encryptor_MasterSalt)
 def get_master_salt(self):
     return ESAPI.encoder().decode_from_base64(
         settings.Encryptor_MasterSalt)
Exemple #34
0
 def test_encode_for_ldap(self):
     instance = ESAPI.encoder()
     self.assertEquals(None, instance.encode_for_ldap(None))
     self.assertEquals("Hi This is a test #��", instance.encode_for_ldap("Hi This is a test #��") ,"No special characters to escape")
     self.assertEquals("Hi \\00", instance.encode_for_ldap("Hi " + unichr(0)), "Zeros")
     self.assertEquals("Hi \\28This\\29 = is \\2a a \\5c test # � � �", instance.encode_for_ldap("Hi (This) = is * a \\ test # � � �"), "LDAP Christams Tree")
    def execute_system_command(self, executable, params, parent_dir, working_dir=None, codec=None, log_params=True):

        if codec is None:
            codec = self.codec

        if working_dir is None:
            working_dir = self.working_dir

        try:
            # Executable must exist
            if not os.path.exists(executable):
                raise ExecutorException(
                    _("Execution failure"), _("No such executable: %(executable)s") % {"executable": executable}
                )

            directory, filename = os.path.split(executable)

            # executable must use canonical path
            if not ESAPI.validator().is_valid_directory_path("Executor", directory, parent_dir, False):
                raise ExecutorException(
                    _("Execution failure"), _("Directory did not pass validation: %(dir)s") % {"dir": directory}
                )

            # Must be in approved list
            approved = ESAPI.security_configuration().get_allowed_executables()
            if executable not in approved:
                raise ExecutorException(
                    _("Execution failure"),
                    _(
                        "Attempt to invoke executable that is not listed as an approved executable in configuration: %(executable)s"
                    )
                    % {"executable": executable},
                )

            # Escape parameters
            params = [ESAPI.encoder().encode_for_os(codec, param) for param in params]

            # Working directory must exist
            if not os.path.exists(working_dir):
                raise ExecutorException(
                    _("Execution failure"),
                    _("No such working directory for running executable: %(dir)s") % {"dir": working_dir},
                )

            args = params
            args.insert(0, executable)
            start_time = datetime.now()
            proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=working_dir)

            if log_params:
                self.logger.warning(
                    Logger.SECURITY_SUCCESS,
                    _("Initiating executable %(args)s in %(dir)s") % {"args": str(args), "dir": working_dir},
                )
            else:
                self.logger.warning(
                    Logger.SECURITY_SUCCESS,
                    _("Initiating executable %(executable)s in %(dir)s") % {"executable": args[0], "dir": working_dir},
                )

            while proc.poll() is None and datetime.now() - start_time < self.max_running_time:
                time.sleep(1)

            if proc.poll() is None:
                # Kill the process because it ran too long
                proc.terminate()
                time.sleep(1)
                if proc.poll() is None:
                    proc.kill()
                raise ExecutorException(
                    _("Execution failure"),
                    _("Process exceeded maximum running time and was killed: %(executable)s")
                    % {"executable": executable},
                )

            else:
                # Process terminated in allotted timeframe
                stdout_and_err = proc.communicate()
                return stdout_and_err
        except Exception, extra:
            raise ExecutorException(
                _("Execution failure"), _("Exception thrown during execution of system command"), extra
            )
        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)