Using LLDP to deliver XSS payloads to Zyxel GS1900
Earlier this year I took a closer look again at the Zyxel GS1900-8 switch. Last time I mainly looked at the firmware itself, however this time I took a closer look at a different vector to test this device.
Link Layer Discovery Protocol (LLDP)⌗
Based on an educated guess I started poking around the LLDP pages on the web interface. LLDP is a layer 2 network protocol described in IEEE 802.1AB. It is used for neighbor discovery and for exchanging information between LLDP-capable systems on the same physical network.
Each LLDP frame consists of four required TLVs and zero or more optional TLVs. TLVs are type-length-value structures, sometimes also named “fields”. Each value part of a TLV can be up to 512 octects, or bytes.
Most managed switches have some way of sending and receiving LLDP frames and it’s pretty handy to figure out what physical port switch A is connected to on switch B, among other things. This information is stored in the required fields.
In addition four required TLVs, there are some optional TLVs which you can provide. These tend to be “free form” fields which con be used for a system name, system description and a few others…see where I’m going with this?
Depending on the web interface of a particular switch you can send it up to 512 bytes of arbitrary for it to interpret and render.
PoC⌗
Let’s cut to the chase, using lldpcli on a system directly connected to this switch I was able to trivially inject a cross-site scripting (XSS) payload:
[lldpcli] # configure system description <a\ href="#"\ onclick="alert('pwnie')">test</a>
[lldpcli] # update
Note that we only have to escape whitespace here. On switch this can be triggered by navigating to Monitor -> LLDP -> Remote information -> select a magnifying glass.
and then clicking the rendered link:
This does require either an enticing link text or some other social engineering magic to get an administrator to click the click, but you get the gist. Further exploitation does require bypassing the strict Content Security Policy which is set by the webserver…this is not something you see a lot on this type of devices! But given the fact you have a multiple of 512 bytes per displayed TLV, there’s plenty of room for experimentation. If anything, this demonstrates that LLDP is a valid attack vector for performing XSS attacks, and YMMV depending on the device you’re dealing with.
I’ve tested a few similar SMB/SOHO managed switches and most of them lack the CSP headers, but they do require some more String.fromCharCode()
fu to bypass some filters.
Conclusion⌗
The LLDP issue was reported to Zyxel in March and has been fixed with firmware updates which are released today. The issue was assigned CVE-2021-35030. While the actual PoC isn’t all that spectacular, it does show that LLDP is in interesting attack vector that some vendors have overlooked.