Problem
You want to reverse the weak Cisco password encryption algorithm to recover forgotten passwords.
Solution
To recover a lost router password from a configuration file, use the following Perl script to decipher weakly encrypted passwords. This script expects to read router configuration commands via standard input (STDIN). It then prints the same commands to standard output (STDOUT) with the passwords decrypted.
Here is an example of the program's output:
Freebsd% cpwcrk.pl < Router1-confg version 12.2 service password-encryption ! hostname Router1 ! enable secret 5 $1$4y6Q$bcGReJ3kGgmlpfr7/lT64. enable password 7 06150E2F4A5C0817 (decrypted: sanfran) ! username ijbrown password 7 121A0C041104 (decrypted: cisco) username kdooley password 7 1306181D000E0B2520 (decrypted: cookbook) ! ! line con 0 password 7 06120A22445E1E1D (decrypted: techpwd) line aux 0 password 7 0212015803161825 (decrypted: techpwd) line vty 0 4 password 7 070033494705151C (decrypted: oreilly) login ! end
The program in Example 3-2 is written as a Perl script.
Example 3-2. cpwcrk.pl
#!/usr/local/bin/perl # # cpwcrk.pl -- a small script to crack Cisco's Type 7 password # encryption # # $k='dsfd;kfoA,.iyewrkldJKDHSUB'; for($i=0; $i) { if(/ord 7 [01]/) { chop; $w=$_; s/.* //g; $C = $_; printf "$w (decrypted: "; $o=substr($C, 0, 2); for ($i=0; $i < (length($C)-1)/2; $i++) { $cs[$i]=hex(substr($C,2*$i,2)); } for ($j=1; $j < $i; $j++) { printf("%c", $ks[$o+$j-1] ^ $cs[$j]); } printf ") "; } else { printf $_; } } |
|
Discussion
This little Perl script is deliberately written to be small and fast, which unfortunately makes it somewhat difficult to read. We will give a brief explanation of how it works.
The first thing it does is to take the standard key string, $k, and translate it into an array of hexadecimal numbers, $ks, to make it easier to work with. Then it reads the input configuration file one line at a time, looking for any password 7 lines. To make the search slightly quicker, the script only looks for the string ord 7, followed by a space and either the number 0 or 1. It stores the encrypted password string in the variable $C.
The first two characters in the encrypted string are used for an offset, so the script stores them in the string, $o. It then goes through the crypt string, two characters at a time, and converts the result into hexadecimal, which it stores in the array, $cs.
The script then does all of the actual decryption work in a simple loop that calculates an XOR (exclusive OR) operation between the offset original key and the elements of the $cs array.
The encryption algorithm is nothing more than a bitwise XOR between the password string and a known key offset by a random amount. This random offset is encoded into the first two characters of the result, so it is easy to uniquely reverse the cipher.
Cisco chose to use such a simple algorithm because the router needs to be able to uniquely decrypt passwords for some applications, such as CHAP authentication. This is different from most password applications in which the device can take an incoming password string, encrypt it with a one-way algorithm, and compare the resulting encrypted version with the encrypted version of the locally stored password. In those applications it is sufficient to work only with the encrypted versions of the passwords.
See Also
Recipe 3.2; Recipe 3.3; Recipe 3.4
Router Configuration and File Management
Router Management
User Access and Privilege Levels
TACACS+
IP Routing
RIP
EIGRP
OSPF
BGP
Frame Relay
Handling Queuing and Congestion
Tunnels and VPNs
Dial Backup
NTP and Time
DLSw
Router Interfaces and Media
Simple Network Management Protocol
Logging
Access-Lists
DHCP
NAT
First Hop Redundancy Protocols
IP Multicast
IP Mobility
IPv6
MPLS
Security
Appendix 1. External Software Packages
Appendix 2. IP Precedence, TOS, and DSCP Classifications
Index