Making a Killer BPDU

Snip, snip your spanning tree!

While studying for the CCNA or similar exams like the CompTIA Network+, students are introduced to the Spanning Tree Protocol. It's a simple idea. Network loops are a problem inherent to the basic functionality of network switches, so it's necessary to run some kind of protocol to detect these loops and plug them in a way that will do the least damage to network operations - or at least, does less damage than its absence would.

After learning the fundamentals, the student will also be introduced to some basic concepts that will optimise the user experience with a network that's running spanning-tree, like Portfast and BPDUguard. However, those concepts aren't quite as flashy as other topics like OSPF areas and BGP route-mapping. As such, when this student enters the workforce, they'll most likely start working on a network with a "works well-enough not to touch" STP configuration. After all, if you touch it, anything that happens to it from then on will become your problem.

I recently had the misfortune of running into (read: causing) an STP-based problem. It wasn't a switching-loop, as one might expect, but rather, a switchport that was supposed to be connected to a management port of another switch, was actually connected to a data port. This connection - even if it wasn't a loop - still caused a BPDU to come into the network. That's not really an issue if you're working with a regular network, but if you're running a PTP-based SMPTE-2110 network, milliseconds count.

That single BPDU caused a topology change notification (TCN) to get through the entire network, clearing out MAC address tables as it went. Only when all the switches were once again in agreement on how the spanning-tree topology should be, was when everything returned to normal.

Obviously my employer didn't very much enjoy all of this, but I secretly did. It was great fun to figure out what actually went wrong. Troubleshooting always has been my favourite part of the job. And as it turns out, the mitigation is quite simple. Just use those boring bits of the CCNA material! It really is that easy. Enabling bpduguard on an interface will shut down the interface and keep it from registering as a topology change.

So now let's turn what we learned into a weapon!

Topology Setup

We're going to take a host, wire it up to a switch, and then a second switch will connect to the first, like so:

And because we're working entirely in layer 2, we don't even have to do any configuration.

Payload design

Next up, we want to figure out what we want to tell the switch such that it will send a TCN to its neighbour.

When it comes to Ethernet, we luckily don't have to configure much. Just the source MAC address. We can be honest and use our interface's actual MAC address, or we can just make something up. Seeing as I'm trying to really mess with this network, and if we were to send this to a switch with a bridge ID also set to 0, the next thing we can do to get ourselves elected is to have the lowest MAC address, so I'll go with 00:00:00:00:00:01

>>> ether_frame = Dot3(src="00:00:00:00:00:01", dst="01:80:c2:00:00:00") # standard STP dst MAC.

Great! Now we just set the Bridge ID to 00:00:00:00:00:01 with priority 1, and do the same for the Root ID.

>>> bpdu = ether_frame/STP(version=3, bpdutype=2, bpduflags=0x3c, rootid=1, rootmac=00:00:00:00:00:01, bridgeid=1, bridgemac=00:00:00:00:00:01)

Now we just send if off!

>>> sendp(bpdu, iface=INTERFACE_NAME)

Success!

We may not have hijacked the tree permanently, but we did manage to cause both SW1 and SW2 to flush their entire MAC address table with no authentication at all!

I saved the packet to a .pcap, so you can use it too if you want! Here's a link!