Encrypting Passwords

Encrypting Passwords

Problem

You want to encrypt passwords so that they do not appear in plain text in the router configuration file.

Solution

To enable password encryption on a router, use the service password-encryption configuration command:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#enable password oreilly
Router1(config)#line vty 0 4
Router1(config-line)#password cookbook
Router1(config-line)#line con 0
Router1(config-line)#password cookbook
Router1(config-line)#line aux 0
Router1(config-line)#password cookbook
Router1(config-line)#exit
Router1(config)#service password-encryption
Router1(config)#end
Router1#

This command uses a weak, reversible encryption method to encipher VTY and enable passwords. Please see Recipe 3.5 for more details.


Discussion

By default, the router stores all passwords in clear text and presents them in a human-readable format when you look at the router's configuration. The service password-encryption command encrypts the passwords by using the Vigenere encryption algorithm. Unfortunately, the Vigenere encryption method is cryptographically weak and trivial to reverse, as we will illustrate in Recipe 3.5.

However, this functionality is still quite useful to prevent nosy neighbors from viewing passwords over your shoulder. As such, encrypting your passwords is still highly recommended in spite of the known weaknesses. You should be aware of the inherent weaknesses of this encryption scheme when storing or forwarding router configuration files, though. Recipe 3.4 provides a small utility to strip your router configuration files of all passwords (encrypted or not) to keep stored and forwarded configuration files safe from prying eyes.

The following example shows what a configuration file looks like with password encryption enabled:

Router1#show running-config 
Building configuration...

Current configuration : 4385 bytes
!
! Last configuration change at 13:08:35 EDT Thu Jun 27 2002 by weak
! NVRAM config last updated at 13:01:45 EDT Thu Jun 27 2002 by kdooley
!
version 12.2
service password-encryption

!
hostname Router
!
enable password 7 06091D2445420500
!
username ijbrown password 7 045802150C2E
username kdooley password 7 070C285F4D06
!
line con 0
password 7 0605002E474C06160E
line aux 0
password 7 151104030F28242B23
line vty 0 4
password 7 110A160A1C1004030F
!
end

You will notice that the router now encrypts all of the passwords and no longer displays them in a human-readable format.

See Also

Using Better Password-Encryption Techniques

Using Better Password-Encryption Techniques

Problem

You want to assign a privileged password with a stronger encryption standard than Cisco's trivial default encryption.

Solution

To enable strong, nonreversible encryption of the privileged password, use the enable secret configuration command:

Router1#configure terminal  
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#enable secret ORAbooks
Router1(config)#end
Router1#

Beginning with IOS Version 12.2(8)T, Cisco introduced strong encryption for its username command as well. To enable strong encryption for router usernames, use the username secret command:

Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#username ijbrown secret oreilly
Router(config)#end
Router#

Discussion

Cisco introduced the enable secret password to improve the security of the enable password command. This command uses the cryptographically strong MD5 algorithm to encrypt passwords. It it extremely difficult to crack this algorithm. In fact, there are no known ways to uniquely reverse MD5 encryptions, which is why it is called a nonreversible algorithm.

When you configure the router with an enable secret password, it will encrypt your enable password whether you have the service password-encryption command or not. The service password-encryption command has no effect on the enable secret password.

Configuring a nonreversible enable password provides greater security than the traditional enable password command. It is useful in environments that store or transfer configuration files across the network. The enable secret password takes precedence over the enable password. So if you have both types of enable passwords configured, the router will only use the secret version. We highly recommend using the enable secret password on all routers.

The following command shows what the enable secret command looks like when you look at the router's configuration file:

Router1#show running-config | include secret
enable secret 5 $1$Ahxf$4OivEQn0n0JneSObfRdSw0
Router1#

The following is a list of enable secret password restrictions:

  • The password must contain between 1 and 25 alphanumeric characters (upper- or lowercase).

  • Leading spaces are ignored while intermediate and trailing spaces are permitted and recognized.

  • You can use a question mark, "?", in the password, but only if you precede the question mark with a "Control v" (the Ctrl key and the letter v key).

You should never use the same password for the enable password and enable secret commands. The router will warn you against doing this, but it will accept it:

Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#enable password cisco
Router1(config)#enable secret cisco
The enable secret you have chosen is the same as your enable password.
This is not recommended. Re-enter the enable secret.

Router1(config)#end
Router1#

Setting the same password for both commands defeats the purpose of using the enable secret command in the first place and renders its strong encryption useless. Avoid this problem by choosing a different password or removing the enable password altogether.

Cisco introduced the username secret command in Version 12.2(8)T to provide an added layer of security over the username password command. It provides greater security by using the same irreversible MD5 encryption as the enable secret command. However, because the password is not retrievable, some protocols that require clear test passwords, such as CHAP, will not work with the strong encryption.

Even strong encryption is vulnerable to dictionary and brute force attacks. To protect against such attacks, ensure that all of your passwords are difficult to guess and avoid using words found in the dictionary. For example, a common password-cracking program took less than a minute to find the password "cookbook11".


See Also

Setting Up User IDs

Setting Up User IDs

Problem

You want to assign individual (or group) user IDs and passwords to network staff.

Solution

To enable locally administered user IDs, use the following set of configuration commands:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#username ijbrown password oreilly
Router1(config)#username kdooley password cookbook
Router1(config)#aaa new-model
Router1(config)#aaa authentication login local_auth local
Router1(config)#line vty 0 4
Router1(config-line)#login authentication local_auth
Router1(config-line)#exit
Router1(config)#end
Router1#

The username command also allows you to create usernames without passwords by specifying the nopassword keyword:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#username weak nopassword
Router1(config)#aaa new-model
Router1(config)#aaa authentication login default local
Router1(config)#end
Router1#

However, we strongly recommend against doing this because it can severely weaken the router's security.

Discussion

Enabling locally administered usernames overrides the default VTY password-based authentication system. When you enable the aaa new-model command, as shown in this recipe, the router will immediately begin to prompt for usernames as well as passwords. Assigning unique usernames to individuals or groups provides accountability, as we will show later. The following example shows the login prompt for a router using local authentication:

Freebsd%telnet Router1
Trying 172.25.1.5...
Connected to Router1.
Escape character is '^]'.

User Access Verification

Username: ijbrown
Password:

Router1>

The router prompts for the username as well as the password. Compare this to how the router behaves when just a password is set on the VTY lines:

Freebsd%telnet Router2
Trying 172.25.1.6...
Connected to Router2.
Escape character is '^]'.

User Access Verification

Password:

Router2>

When you configure locally administered usernames, the router will prompt for usernames on all lines, including the console and AUX ports, as well as the VTY ports used for Telnet sessions. To avoid locking yourself out of the router, you should always configure a username command before entering the AAA commands. It also is a good idea to use another session terminal to test the new authentication system before logging out of your original session. If you do accidentally lock yourself out of the router, you will need to follow the normal password-recovery procedures for your router type. We discuss AAA commands further in Chapter 4.

Locally administered usernames work well in a small environment with a limited number of administrators. However, this method does not scale well to a large network with many administrators. Keeping usernames synchronized across an entire network can become quite daunting. Fortunately, Cisco also supports an advanced authentication methodology called Authentication, Authorization, and Accounting (AAA), which we discuss in Chapter 4. AAA provides a centralized server that administers usernames and passwords (among other features).

Enabling username support causes the router to associate certain functions with usernames. This provides accountability for each username by showing exactly who is doing what. For instance, the output of the show users command will include active usernames:

Router1>show users
Line User Host(s) Idle Location
66 vty 0 ijbrown idle 00:36:21 freebsd.oreilly.com
67 vty 1 kdooley idle 00:00:24 server1.oreilly.com
* 68 vty 2 weak idle 00:00:00 freebsd.oreilly.com

Interface User Mode Idle Peer Address

Router1>

More importantly, log messages will capture the username of the individual who invoked certain high-profile commands, such as configuration changes, the clearing of counters, and reloads. For example:

Jun 27 12:58:26: %SYS-5-CONFIG_I: Configured from console by ijbrown on vty2 (172.25.1.1)
Jun 27 13:02:22: %CLEAR-5-COUNTERS: Clear counter on all interfaces by weak on vty2 (172.25.1.1)
Jun 27 14:00:14: %SYS-5-RELOAD: Reload requested by kdooley on vty0 (172.25.1.1).

Notice that these log messages now include the username associated with each action. So instead of just knowing that somebody changed the configuration or reloaded the router, you can see exactly who did it.

In addition, the router captures the username of the last person to modify its configuration or save the configuration to NVRAM, which is visible using the show running-config:

Router1#show running-config 
Building configuration...

Current configuration : 4285 bytes
!
! Last configuration change at 12:58:26 EDT Fri Jun 27 2003 by ijbrown
! NVRAM config last updated at 13:01:45 EDT Fri Jun 27 2003 by kdooley
!
version 12.2

The username command also has an autocommand keyword, which you can use to assign an EXEC level command to a particular username. This is useful when you want to provide limited access to a particular command, while restricting access to everything else on the router. For example, you might want to set up a special username that anybody could use to run a single router command, and then terminate the session:

Router1#configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Router1(config)#aaa new-model
Router1(config)#aaa authentication login default local
Router1(config)#aaa authorization exec default local
Router1(config)#username run nopassword noescape
Router1(config)#username run autocommand show ip interface brief
Router1(config)#end
Router1#

In this example, we defined the username run without a password and assigned it an autocommand of show ip interface brief. When you log in to the router with this username, the router will not prompt for a password. It will just automatically execute the command and then terminate the session:

Freebsd% telnet Router1
Trying 172.22.1.4...
Connected to Router1.
Escape character is '^]'.

User Access Verification

Username: run
Interface IP-Address OK? Method Status Protocol
BRI0/0 unassigned YES NVRAM administratively down down
Ethernet0/0 172.25.1.8 YES NVRAM administratively down down
BRI0/0:1 unassigned YES unset administratively down down
BRI0/0:2 unassigned YES unset administratively down down
FastEthernet1/0 172.22.1.4 YES NVRAM up up
Loopback0 192.168.20.1 YES NVRAM up up Connection closed by foreign host.
Freebsd%

Notice how the router issued the command and then terminated the session without providing the opportunity to issue another command.

The noescape keyword prevents the user from issuing an escape sequence to access the router EXEC. We strongly recommend using this keyword whenever you use autocommands.

See Also

Generating a Server Host Table File cp3

Generating a Server Host Table File

Problem

You want to build a detailed host file containing the IP addresses and interface names of all of your routers.

Solution

The Perl script in Example 2-4, host.pl, builds a detailed host table that includes all of the IP addresses on each router in a list of devices. The script is written in Perl and requires NET-SNMP to extract data from the router list. No arguments are expected or required.

Example 2-4. host.pl

#!/usr/local/bin/perl
#
# host.pl -- a script to build a detailed host file from
# information gathered from a router list.
#
#Set behavour
$workingdir="/home/cisco/net";
$snmpro="ORARO";
#
$rtrlist="$workingdir/RTR_LIST";
$snmpwalk="/usr/local/bin/snmpwalk -v 1 -c $snmpro";
$snmpget="/usr/local/bin/snmpget -v 1 -c $snmpro";
open (RTR, "$rtrlist") || die "Can't open $rtrlist file";
open (RESULT, ">$workingdir/RESULT") || die "Can't open RESULT file";
while () {
chomp($rtr="$_");
@ifIndex=\Q$snmpwalk $rtr ipAdEntIfIndex\Q;
@ipAddress=\Q$snmpwalk $rtr ipAdEntAddr\Q;
$rtr1=\Q$snmpget $rtr .1.3.6.1.4.1.9.2.1.3.0\Q;
chomp(($foo, $RTR) = split (/"/, $rtr1));
$arraynum=0;
for $ifnumber (@ifIndex) {
chomp(($foo, $ifnum) = split(/= /, $ifnumber));
$ifDescription=\Q$snmpget $rtr ifName.$ifnum\Q;
chomp(($foo, $ipaddr) = split(/: /, $ipAddress[$arraynum]));
chomp(($foo, $ifdes) = split(/= /, $ifDescription));
$name="$RTR-$ifdes";
#$name=~s/\//-/;
if ( $ifdes eq "Lo0" ) { $name=$RTR };
print RESULT "$ipaddr\t\t$name\n";
$arraynum++;
}
}
close(RTR);
close(RESULT);

Discussion

Most organizations manually build a host table for their management server(s) with a single IP entry per router, usually the loopback IP address. This script automatically builds a host file that contains all known IP addresses for each router.

Here is an example of the output from the host.pl script:

10.1.1.1                miami-Se0/0
10.2.2.2 miami
172.20.6.8 miami-Se0/2
172.22.1.4 miami-Fa1/0
172.25.1.8 miami-Et0/0
10.1.1.2 toronto-Se0/1
172.20.1.1 toronto-Se0/0.2
172.22.1.1 toronto-Fa0/1
172.25.1.5 toronto-Fa0/0.1
172.25.2.1 toronto-Se0/0.1
172.25.25.1 toronto
172.25.26.5 toronto-Lo1
10.1.99.55 detroit-BR0
172.25.3.7 detroit-Et0
172.25.25.6 detroit
172.20.1.2 boston-Se0.1
172.20.10.1 boston-Et0
172.20.100.1 boston

This output is in the format required for a Unix /etc/hosts file. The script extracts the IP address information via SNMP, and then associates each address with the related router name and interface. The script also automatically creates a primary host entry for each router using the address of the loopback0 interface, but with no interface information in the hostname. So, in this example, you can reach the router located in Boston with hostname boston rather than the less intuitive boston-Lo0.

Having a detailed host file is useful for many reasons. Sometimes the router will send a message to your server, either using SNMP or Syslog, and use the IP address of the interface instead of a main loopback interface. Also, having a detailed host file makes the output of a traceroute much easier to understand:

Freebsd% traceroute miami
traceroute to miami (10.2.2.2), 64 hops max, 52 byte packets
1 detroit-Et0 (172.25.3.7) 2.263 ms 2.210 ms 2.178 ms
2 toronto-Fa0/0.1 (172.25.1.5) 3.042 ms 3.060 ms 3.846 ms
3 boston-Se0.1 (172.20.1.2) 8.234 ms 8.245 ms 8.145 ms
4 miami-Se0/2 (172.20.6.8) 9.893 ms 9.893 ms 9.432 ms
Freebsd%

This makes it much easier to decipher the path between the management station and the Miami router. Not only can we tell which routers lie along the path, but we can also clearly see which interfaces a packet sent along this path will use.

The script does not update the /etc/hosts file directly. You may need to manually import the script's output file into your system's /etc/hosts file. However, you can make this task easier by building a master file containing your normal host information and concatenating this master file together with the script output. This way you could even use the cron utility to automatically run this script and create a new up-to-date host file on a nightly basis.

Before the script will work, you must modify two variables. The $workingdir variable must be set to the directory that you will launch the script from. The $snmpro variable must be set to your SNMP read-only community string. The script assumes that you use the same read-only community string on all of your routers.

The script reads through a router list, and queries each device in sequence. It expects to find this list in a file called RTR_LIST in the working directory. The list can contain router names or IP addresses, with one entry per router, and one router per line. The script will extract the hostname directly from the router, so you should also ensure that all of your routers are configured with unique hostnames. The results of the script are stored in a file called RESULT, contained in the working directory.

As a final note, we should mention that this script can generate hostnames that do not confirm to RFC 952, "DOD INTERNET HOST TABLE SPECIFICATION," which defines the official rules for hostnames. This is because the script can create hostnames with a "/" character in them, such as miami-Se0/2. This may cause problems for some applications, particularly if they use URL format addressing. For example, a query to http://miami-Se0/2 will clearly cause problems because the last character, 2, will be interpreted as a filename. However, most common applications, such as ping and Telnet, will accept this hostname without any complaints.

If you are a purist, or if you have applications that complain about these hostnames, we've included a line in the script that you can use to convert all of the slashes, "/", to dashes, "-". This line is currently commented out, but you can invoke it by simply removing the comment character, "#", to change this line:

#$name=~s/\//-/;

to this:

$name=~s/\//-/;

See Also

Generating a Report of ARP Table Information

Generating a Report of ARP Table Information

Problem

You need to extract the ARP table from one of your routers to determine the MAC address associated with a particular IP address or the IP address for a particular MAC address.

Solution

The script in Example 2-3, arpt.pl, extracts the ARP table for a specified router or IP address and displays the results to standard output. The script expects to find a hostname or IP address of a router on the command line.

Example 2-3. arpt.pl

#!/usr/local/bin/perl
#
# arpt.pl -- a script to extract the ARP cache from a router.
#
#Set behavour
$snmpro="ORARO";
#
$snmpwalk="/usr/local/bin/snmpwalk -v 1 -c $snmpro";
$snmpget="/usr/local/bin/snmpget -v 1 -c $snmpro";
chomp ($rtr=$ARGV[0]);
if ( $rtr eq "" ) {die "$0: Must specify a router \n"};
@iftable=\Q$snmpwalk $rtr ifDescr\Q;
for $ifnum (@iftable) {
chomp (($intno, $intname) = split (/ = /, $ifnum));
$intno=~s/.*ifDescr\.//;
$intname=~s/"//gi;
$arpint{$intno}=$intname;
}
printf ("%-22.22s %-10.10s %-25.25s\n", Address, MAC, Interface);
@atTable=\Q$snmpwalk $rtr .1.3.6.1.2.1.3.1.1.1\Q;
for $atnum (@atTable) {
chomp (($atip, $atint) = split (/ = /, $atnum));
$atip =~ s/.*atIfIndex\.[0-9]+\.1\.//;
$atphys=\Q$snmpget $rtr atPhysAddress.$atint.1.$atip\Q;
chomp(($foo, $phys) = split(/: /, $atphys));
$phys=~s/ /-/gi; chop ($phys);
$phys=~tr/A-Z/a-z/;
$int=$arpint{$atint};
printf ("%-15.15s %17.17s %-25.25s\n", $atip, $phys, $int);
}

Discussion

The arpt.pl script extracts the ARP table from a specific router using SNMP and displays it to standard output. The script requires Perl and NET-SNMP, and it expects to find both in the /usr/local/bin directory. For more information on Perl or NET-SNMP, please see Appendix A.

Before using the script, you need to set the SNMP read-only community string, which is contained in the variable $snmpro:

Freebsd% ./arpt.pl toronto
Address MAC Interface
172.22.1.1 00-01-96-70-b7-81 FastEthernet0/1
172.22.1.2 00-01-96-70-b7-81 FastEthernet0/1
172.22.1.3 00-01-96-70-b7-81 FastEthernet0/1
172.25.1.1 00-10-4b-09-57-00 FastEthernet0/0.1
172.25.1.5 00-01-96-70-b7-80 FastEthernet0/0.1
172.25.1.7 00-00-0c-92-bc-6a FastEthernet0/0.1
172.25.1.254 00-00-0c-07-ac-01 FastEthernet0/0.1
172.16.2.1 00-01-96-70-b7-80 FastEthernet0/0.2
172.16.2.22 00-00-0c-07-ac-00 FastEthernet0/0.2
Freebsd%

The script creates a simple report, including the IP address, MAC address, and interface name of each ARP entry. You can then use a search utility of some kind to locate specific devices by its IP or MAC address. For example, on a Unix server, you could pipe the output to the grep command, as follows:

Freebsd% ./arpt.pl toronto | grep 172.25.1.5
172.25.1.5 00-01-96-70-b7-80 FastEthernet0/0.1
Freebsd%

The ARP tables on large routers can be quite large, which can make locating a single ARP entry difficult. This script allows you to track down a particular device remotely. You could also use the grep utility to find the IP address of a particular known MAC address:

Freebsd% ./arpt.pl toronto | grep 00-10-4b-09-57-15
172.25.1.3 00-10-4b-09-57-15 FastEthernet0/0.1
Freebsd%

This script only queries open standard SNMP MIBS, so you can use it to extract ARP table information from almost any SNMP enabled device, even nonCisco equipment.

See Also