Authentication on Cisco IOS
Let’s have a look at how Cisco IOS handles authentication and how passwords are stored in the configuration file.
Disable Cleartext Passwords in the Configuration File
Let’s I set the “front-door password” for console access that would put the user in user EXEC mode:
ISR4321# conf t
ISR4321(config)# line console 0
ISR4321(config-line)# password foobarbaz
ISR4321(config-line)# login
ISR4321(config-line)# ^Z
ISR4321# sh run | b line
line con 0
!
line aux 0
!
line vty 0 4
password foobarbaz
login
line vty 5 15
password foobarbaz
login
!
To obfuscate passwords in the configuration file:
ISR4321(config)# service password-encryption
Passwords that are normally be stored in plaintext in the config file will now be obscured by “Type 7 encryption”.1 “Encryption” sounds like a big deal, but this type of encryption is merely meant to prevent casual shoulder surfing:
line con 0
password 7 1047021200
login
Type 7 “encryption” is seriously broken. So consider anyone with access to the config (or backups thereof) to know the password and be able to access user EXEC mode on your Cisco devices.
If we were to exit
now, we would be prompted for this front-door password:
ISR4321# exit
ISR4321 con0 is now available
Press RETURN to get started.
User Access Verification
Password:
ISR4321>
The router does not echo the password back to the screen to prevent shoulder surfing.
Protect Privileged EXEC Mode with a Password
Set the “enable” password (to get to enable/privileged EXEC mode):
ISR4321(config)# enable secret algorithm-type scrypt secret <pwd>
At least on my IOS, fortunately, scrypt
is available as a PBKDF.2
When enable secret
is set, IOS will ignore the enable password
. That means
that if both are set, you can only gain access with the enable secret
password. enable password
stores the password in plaintext in the config file,
or merely obfuscates it when service password-encryption
is set. So remove
this insecure password with no enable password
.
Username + Password Authentication
You can also use username + password authentication. Logins over console and Telnet can then request a username in addition to a password. SSH always requires both a username and a password.
Create users with usernames, password and privilege levels:
ISR4321(config)# username stefan privilige 15 secret stefanpwd
ISR4321(config)# username thomas privilige 1 secret stefanpwd
You can use algorithm-type
to specify the PBKDF. On my IOS, by default, it
uses the (weak) MD5. Use scrypt
instead.
By changing line console 0
to use login local
instead of login
, the login
prompt will request credentials from the local list configured with username <name> secret <secret>
:
ISR4321# conf t
ISR4321(config)# line console 0
ISR4321(config-line)# login local
ISR4321(config-line)# end
ISR4321# exit
User Access Verification
Username: thomas
Password:
ISR4321>
If we authenticate with the privileged user stefan
instead (which was
configured with privilege 15
), we are taken straight to enable/privileged EXEC
mode after authentication.
Secure SSH and/or Telnet with ACLs
To secure logging in over IP, ACLs are needed. After all, you can have a strong password, but if Cisco’s SSH or Telnet daemon has a vulnerability, you would still want to prevent the baddies from knocking on those exposed ports.
First, create an standard numbered ACL:
ISR4321(config)#access-list 1 permit 172.16.0.0 0.15.255.255
This permits all hosts with a source IP address in the RFC 1918 private IP
subnet 172.16/12. ACLs in Cisco land always end with default deny. So this
reads: allow IP packets from source 172.16/12 and drop the packets otherwise.
The wildcard mask (0.15.255.255
) is a mask that defines which bits of the
source address will be checked against the defined ACL base address.
Say, a packet with source IP 172.16.123.123 comes in:
base = 1010 1100 0001 0000 0000 0000 0000 0000
mask = 0000 0000 0000 1111 1111 1111 1111 1111
check = 1010 1100 0001 0000 0111 1011 0111 1011
If we compare base
with check
for every bit where the mask
has a 0
bit,
we see that base == check
. And so the ACL matches and traffic is allowed to
flow. Internally, Cisco probably just logically ORs the base
and mask
(base | mask
) and mask
and check
(mask | check
) and compares the results.
Currently, this ACL is not assigned to a port or a vty though, so it does not do anything.
ISR4321(config)#line vty 0 15
ISR4321(config-line)#access-class 1 in
Here, we assign the standard numbered ACL with identifier 1
to all the vty
lines.
The in
keyword specifies the direction of the traffic flow: in this case, we
anticipate a remote client initiating a connection with the Cisco device. You
could also specify out
. The ACL would then filter outgoing connection made
from the Cisco device by the user connected over a vty line. The single IP
address in the standard ACLs is then interpreted as a destination rather than
a source IP address. When using extended ACLs (100-199 and 2000-2699) for
access-class
, you should use the any
keyword for either the source or
destination address, depending on whether ingress or egress is filtered.
-
Note that if you disable
password-encryption
again, IOS will not decrypt the obfuscated passwords. ↩︎ -
By default, my IOS version (16.06.04) uses the (weak) MD5-based BSD password algorithm 1. If you encounter an enable secret:
Router#sh run | i secret enable secret 5 $1$mERr$jegsBINbJe1/UUQKc.NUC1
You can check the password on a Linux box with
openssl-passwd(1)
:
↩︎openssl passwd -1 -salt mERr foobarbaz $1$mERr$jegsBINbJe1/UUQKc.NUC1