diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-03-10 16:43:05 -0500 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-03-10 16:43:05 -0500 |
| commit | 929d2168c5119c4b9b401e0ece4a39bf8b944b08 (patch) | |
| tree | bbe311ed8fa8cccd397166838fe6ccf488c7e326 /docs | |
| parent | 557d17ba4e0123bce7e1659002270aa8dedb2f24 (diff) | |
| download | passlib-929d2168c5119c4b9b401e0ece4a39bf8b944b08.tar.gz | |
added support for Cisco PIX & Type 7 hashes
* Cisco Type 5 appears to be same as md5_crypt
* added requires_user=False support to HandlerCase
* added more through salt-generation test (since
cisco_pix has only 4 bits of salt)
* added HandlerCase test to ensure user is used as salt
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/lib/passlib.hash.cisco_pix.rst | 146 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.cisco_type7.rst | 134 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.md5_crypt.rst | 33 | ||||
| -rw-r--r-- | docs/lib/passlib.hash.rst | 8 |
4 files changed, 315 insertions, 6 deletions
diff --git a/docs/lib/passlib.hash.cisco_pix.rst b/docs/lib/passlib.hash.cisco_pix.rst new file mode 100644 index 0000000..52ee277 --- /dev/null +++ b/docs/lib/passlib.hash.cisco_pix.rst @@ -0,0 +1,146 @@ +.. index:: cisco; pix hash + +================================================================== +:class:`passlib.hash.cisco_pix` - Cisco PIX hash +================================================================== + +.. currentmodule:: passlib.hash + +This class implements the password hash algorithm commonly found on Cisco +PIX firewalls. + +.. warning:: + + This hash is not secure, and should not be used for any purposes + besides manipulating existing Cisco PIX password hashes. + +.. seealso:: + + * :doc:`passlib.hash.md5_crypt` (referred to as a "type 5" hash by Cisco) + * :doc:`passlib.hash.cisco_type7` + +Usage +===== +.. note:: + + This hash algorithm has a context-sensitive percularity. + It takes in an optional username, used to salt the hash, + but with specific restrictions... + + * The username *must* be provided in order to correctly hash passwords + associated with a user account on the Cisco device. + + * Conversely, the username *must not* be provided (or must be set to ``""``) + in order to correctly hash passwords which don't have an associated user + account (such as the "enable" password). + +This class can be used directly as follows:: + + >>> from passlib.hash import cisco_pix as pix + + >>> # encrypt password using specified username + >>> h = pix.encrypt("password", "user") + >>> h + 'A5XOy94YKDPXCo7U' + + >>> pix.identify(h) #check if hash is recognized + True + >>> pix.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized + False + + >>> pix.verify("password", h, "user") #verify correct password + True + >>> pm.verify("password", h, "other") #verify correct password w/ wrong username + False + >>> pm.verify("letmein", h, "user") #verify incorrect password + False + + >>> # encrypt password without associate user account + >>> h2 = pix.encrypt("password") + >>> h2 + 'NuLKvvWGg.x9HEKO' + + >>> # verify password without associated user account + >>> pix.verify("password", h2) + True + +Interface +========= +.. autoclass:: cisco_pix() + +.. rst-class:: html-toggle + +Format & Algorithm +================== +Cisco PIX hashes consist of a 12 byte digest, encoded as a 16 character +:data:`HASH64 <passlib.utils.h64>`-encoded string. An example +hash (of ``"password"``) is ``"NuLKvvWGg.x9HEKO"``. + +The digest is calculated as follows: + +1. The password is encoded using an ``ASCII``-compatible encoding + (all known references are strict 7-bit ascii, and Passlib uses ``UTF-8`` + to provide unicode support). +2. If the hash is associated with a user account, + append the first four bytes of the user account name + to the end of the password. If the hash is NOT associated + with a user account (e.g. it's the "enable" password), + this step should be omitted. +3. The resulting password should be truncated to 16 bytes, + or the right side NULL padded to 16 bytes, as appropriate. +4. Run the result of step 3 through MD5. +5. Discard every 4th byte of the 16-byte MD5 hash, starting + with the 4th byte. +6. Encode the 12-byte result using :data:`HASH64 <passlib.utils.h64>`. + +Security Issues +=============== +This algorithm is not suitable for *any* use besides manipulating existing +Cisco PIX hashes, due to the following flaws: + +* It's use of the username as a salt value (and only the first four characters + at that), means that common usernames (eg ``admin``, ``cisco``) will occur + more frequently as salts, weakening the effectiveness of the salt in + foiling pre-computed tables. + +* It's truncation of the ``password+user`` combination to 16 characters + additionally limits the keyspace, and the effectiveness of the username + as a salt; making pre-computed and brute force attacks much more feasible. + +* Since the keyspace of ``user+password`` is still a subset of ascii characters, + existing MD5 lookup tables have an increased chance of being able to + reverse common hashes. + +* It's simplicity, and the weakness of MD5, makes high-speed brute force attacks + much more feasible. + +* Furthermore, it discards of 1/4 of MD5's already small 16 byte digest, + making collisions much more likely. + +Deviations +========== +This implementation differs from the standard in one main way: + +* Unicode Policy: + + The official Cisco PIX algorithm is primarily used with ``ascii`` passwords, + how it handles other characters is not known. + + In order to provide support for unicode strings, + PassLib will encode unicode passwords using ``utf-8`` + before running them through this algorithm. If a different + encoding is desired by an application, the password should be encoded + before handing it to PassLib. + +* While this implementation agrees with all known references, + the actual algorithm has not been published by Cisco, so there may be other + unknown deviations. + +.. rubric:: Footnotes + +.. [#] Description of PIX algorithm - + `<http://www.perlmonks.org/index.pl?node_id=797623>`_ + +.. [#] Message threads hinting at how username is handled - + `<http://www.openwall.com/lists/john-users/2010/02/02/7>`_, + `<www.freerainbowtables.com/phpBB3/viewtopic.php?f=2&t=1441>`_ diff --git a/docs/lib/passlib.hash.cisco_type7.rst b/docs/lib/passlib.hash.cisco_type7.rst new file mode 100644 index 0000000..7d9c83b --- /dev/null +++ b/docs/lib/passlib.hash.cisco_type7.rst @@ -0,0 +1,134 @@ +.. index:: cisco; type 7 hash + +================================================================== +:class:`passlib.hash.cisco_type7` - Cisco "Type 7" hash +================================================================== + +.. currentmodule:: passlib.hash + +This class implements the "Type 7" password encoding used Cisco IOS. +This is not actually a true hash, but a reversible encoding of the plaintext +password. Type 7 strings are (and were designed to be) **plaintext equivalent**; +the goal was to protect from "over the shoulder" eavesdropping, and +little else. They can be trivially decoded. **Do not use for any purpose +where actual security is needed**. + +.. note:: + + This implementation should work correctly for most cases, but may not + fully implement some edge cases (see `Deviations`_ below). + Please report any issues encountered. + +.. seealso:: + + * :doc:`passlib.hash.md5_crypt` (referred to as a "type 5" hash by Cisco) + * :doc:`passlib.hash.cisco_pix` + +Usage +===== +This class can be used directly as follows:: + + >>> from passlib.hash import cisco_type7 as ct + + >>> # encode password + >>> h = ct.encrypt("password") + >>> h + '044B0A151C36435C0D' + + >>> #verify correct password + >>> ct.verify("password", h) + True + >>> #verify incorrect password + >>> pm.verify("letmein", h) + False + + >>> #check if hash is recognized + >>> ct.identify(h) + True + >>> #check if some other hash is recognized + >>> ct.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') + False + + >>> # to demonstrate this is an encoding, not a real hash, + >>> # this class supports decoding the resulting string: + >>> ct.decode(h) + "password" + +Interface +========= +.. autoclass:: cisco_type7() + +.. rst-class:: html-toggle + +Format & Algorithm +================== +The Cisco Type 7 encoding consists of two decimal digits +(encoding the salt), followed a series of hexdecimal characters, +two for every byte in the encoded password. +An example encoding (of ``"password"``) is ``044B0A151C36435C0D``. +This has a salt/offset of 4 (``04`` in the example), +and encodes password via ``4B0A151C36435C0D``. + +The algorithm is a straightforward XOR Cipher (though note the description below +may not be entirely correct, see `Deviations`_ for details): + +1. The algorithm relies on the following ``ascii``-encoded 53-byte + secret key:: + + dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87 + +2. A integer salt should be generated from the range + 0 .. 15. The first two characters of the encoded string are the + zero-padded decimal encoding of the salt. + +3. The remaining characters of the encoded string are generated as follows: + For each byte in the password (starting with the 0th byte), + the :samp:`{i}`'th byte of the password is encoded as follows: + + * let ``j=(i + salt) % keylen`` + * XOR the :samp:`{i}`'th byte of the password with the :samp:`{j}`'th byte + of the secret key. + * encode the resulting byte as uppercase hexidecimal, + and append to the encoded string. + +Deviations +========== +This implementation differs from the official one in a few ways. +It may be updated as more information becomes available. + +* Unicode Policy: + + Type 7 encoding is primarily used with ``ASCII`` passwords, + how it handles other characters is not known. + + In order to provide support for unicode strings, PassLib will encode unicode + passwords using ``UTF-8`` before running them through this algorithm. If a + different encoding is desired by an application, the password should be + encoded before handing it to PassLib. + +* Magic Key: + + Some implementations contain a truncated 26-byte key instead of the + 53-byte key listed above. However, it is likely those implementations have an + incomplete copy of the key, as they exhibit other issues as well after + the 26th byte is reached (throwing an error, truncating the password, + outputing garbage), instead of wrapping around to the beginning of the key. + +* Salt Range: + + All known test vectors contain salt values in ``range(0,16)``. + However, the algorithm itself should be able to handle any salt value + in ``range(0,53)`` (the size of the key). For maximum compatibility with + other implementations, Passlib will accept ``range(0,53)``, but only + generate salts in ``range(0,16)``. + +* While this implementation handles all known test vectors, + and tries to make sense of the disparate implementations, + the actual algorithm has not been published by Cisco, + so there may be other unknown deviations. + +.. rubric:: Footnotes + +.. [#] Description of Type 7 algorithm - + `<http://pen-testing.sans.org/resources/papers/gcih/cisco-ios-type-7-password-vulnerability-100566>`_, + `<http://wiki.nil.com/Deobfuscating_Cisco_IOS_Passwords>`_ diff --git a/docs/lib/passlib.hash.md5_crypt.rst b/docs/lib/passlib.hash.md5_crypt.rst index 538ced5..6305e8f 100644 --- a/docs/lib/passlib.hash.md5_crypt.rst +++ b/docs/lib/passlib.hash.md5_crypt.rst @@ -1,3 +1,5 @@ +.. index:: cisco; type 5 hash + ================================================================== :class:`passlib.hash.md5_crypt` - MD5 Crypt ================================================================== @@ -12,25 +14,41 @@ Security-wise it is considered to be steadily weakening (due to fixed cost), and most unix flavors have since replaced with with stronger schemes, such as :class:`~passlib.hash.sha512_crypt` and :class:`~passlib.hash.bcrypt`. +This is also referred to under Cisco IOS systems as a "type 5" hash. +The format and algorithm are identical, though Cisco seems to require [#cisco]_ +4 salt characters instead of the full 8 characters +used by most systems. + Usage ===== PassLib provides an md5_crypt class, which can be can be used directly as follows:: - >>> from passlib.hash import md5_crypt as mc + >>> from passlib.hash import md5_crypt - >>> mc.encrypt("password") #generate new salt, encrypt password + >>> #generate new salt, encrypt password + >>> h = md5_crypt.encrypt("password") + >>> h '$1$3azHgidD$SrJPt7B.9rekpmwJwtON31' - >>> mc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if hash is recognized + + >>> #verify correct password + >>> md5_crypt.verify("password", h) True - >>> mc.identify('JQMuyS6H.AGMo') #check if some other hash is recognized + >>> #verify incorrect password + >>> md5_crypt.verify("secret", h) False - >>> mc.verify("password", '$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #verify correct password + >>> #check if hash is recognized + >>> md5_crypt.identify(h) True - >>> mc.verify("secret", '$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #verify incorrect password + >>> #check if some other hash is recognized + >>> md5_crypt.identify('JQMuyS6H.AGMo') False + >>> # encrypt password using cisco-compatible 4-char salt + >>> md5_crypt.encrypt("password", salt_size=4) + '$1$wu98$9UuD3hvrwehnqyF1D548N0' + Interface ========= .. autoclass:: md5_crypt() @@ -178,3 +196,6 @@ PassLib's implementation of md5-crypt differs from the reference implementation .. [#f2] Security issues with MD5 - `<http://en.wikipedia.org/wiki/MD5#Security>`_. + +.. [#cisco] Note about Cisco Type 5 salt size - + `<http://serverfault.com/a/46399>`_. diff --git a/docs/lib/passlib.hash.rst b/docs/lib/passlib.hash.rst index 13c2397..dba95c7 100644 --- a/docs/lib/passlib.hash.rst +++ b/docs/lib/passlib.hash.rst @@ -191,6 +191,14 @@ in one of the above categories: .. toctree:: :maxdepth: 1 + passlib.hash.cisco_pix + +* *Cisco "Type 5" hashes* - see :doc:`md5_crypt <passlib.hash.md5_crypt>` + +.. toctree:: + :maxdepth: 1 + + passlib.hash.cisco_type7 passlib.hash.django_std passlib.hash.grub_pbkdf2_sha512 passlib.hash.hex_digests |
