Cisco Type 7 Encryption - What's in a hash?
After setting up the initial configuration on my Catalyst 3550 switches yesterday (see here), I decided to investigate exactly how weak the encryption on the switch’s passwords is. Turns out, a quick google search for “decrypt Cisco passwords” brings up a ton of tools and blog posts to help anyone who can gain access to the Cisco switch config decrypt the password.
Hashing vs Encryption
Interestingly, Cisco has two forms of “encryption” on Catalyst switches: Type 5 and Type 7. Type 5 is used for the secret password that you can set for “enable” mode. Type 7 is used across all other passwords and is activated when you enable the password-encryption services on the switch. Cisco referring to these types as encryption is a misnomer, neither actually uses encryption to process the passwords before storing them.
Instead, both types refer to different hashing functions. Hashing is not the same as encryption. A hash function is intended to only be able to go one way, making it impossible to derive the original string from the hash. This is perfect for passwords as only the user needs to know what the original string is. When the user enters the password string, the system just runs it through the hash function and then compares the resulting hash to the stored hash. Encryption, on the other hand, is intended to be reversable: with a special key you can decrypt the ciphertext back into the original plaintext.
A good hashing function generates a fixed-length string for any amount of data entered into it that cannot be reveresed. If the input changes even a tiny bit, the resulting hash should look completely different. Hashes are commonly cracked with methods like dictionary and brute force attacks, where the attacker keeps guessing the password until login is completed successfully. For a great overview on hashing, check out this site.
Type 5 Passwords
Type 5 is the stronger of the 3550’s two password types and uses the MD5 hash function to obfuscate the stored password. MD5 has been around since the early 90s, so it is no surprise that it has already been severely compromised. However, considering the 3550’s end-of-sale date was in 2006 and many of the more severe attacks on MD5 (see here) came in this decade, MD5 was not a bad choice for a hashing function at the time. Today, though, we know that MD5 is vulnerable to brute-force and collision attacks. In practice, MD5 should not be used as a security mechanism, but is still often used as a checksum for basic data integrity validation caused by unintended corruption.
Type 7 Passwords
The real problem is Cisco’s Type 7 passwords. These use Cisco’s own proprietary algorithm to hash each password. The hash function basically performs an XOR on each character in the password against a hex value in an array. In the resulting hash value, the first hex represents where in the array the XOR began, the rest of the hex values each represent a single character in the password XORed with the value in the array. Since the inverse of XOR happens to be XOR, if you know the array table, deciphering the password is incredibly straightforward. So not only does the length of the hash directly map to the length of the password, the hash is, by each’s very nature, easily reversable.
Most of the scripts I found to decode Cisco’s passwords happen to be in Perl, so for the fun of it, I decided to try my hand at a quick Python script to do the job for me. The following is based on Daren Mattews’ Perl solution found here. I did find another python solution here by jayswan which is similar to mine but didn’t work on the hash values I was pulling out of my 3550’s config.
import sys """ Vigenere translation table """ global xlat xlat = [0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53, 0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36, 0x39, 0x38, 0x33, 0x34, 0x6e, 0x63, 0x78, 0x76, 0x39, 0x38, 0x37, 0x33, 0x32, 0x35, 0x34, 0x6b, 0x3b, 0x66, 0x67, 0x38, 0x37] """ Decryption Algorithm """ def decrypt(password): # Break Cipher into Hex Values password_hex =  for i in range(0,len(password),2): password_hex.append(password[i:i+2]) # Look Up Hex Values in Vigenere translation table password_chars =  index = int(password_hex,16) for i in range(1,len(password_hex)): password_chars.append(chr(int(password_hex[i],16) ^ xlat[index])) index = index + 1 % 53 # wrap around if necessary plaintext = ''.join(password_chars) return plaintext """ Main """ if len(sys.argv) == 2: ciphertext = sys.argv print ("Cipher Text is %s" % ciphertext) print ("Plain Text is %s" % decrypt(ciphertext)) else: print ("Error - Incorrect # of args") print ("Example Usage: python ios7decrypt.py 002D01090A681B0F0B245E")
If you run the above script on the hash 002D01090A681B0F0B245E, you will happily see that at one point I had my switch’s password set to IronSpider. :) You can find this script on GitHub here.
Throughout my 10 year career I have worked as a web developer, systems administrator, software engineer, security analyst and now cybersecurity engineer. I currently develop software applications to automate security vulnerability and compliance scanning and reporting for a multinational financial institution.