Note: since beginning this research back in February, another security researcher @chmod750 has independently discovered and disclosed much of what I am about to talk about!

Introduction

I recently acquired a TP-Link TL-SG108E (V1) Easy Smart switch. The Easy Smart range of switches from TP-Link are targeted at the advanced consumer market; they have some enterprise-class managed switching features such as VLAN tagging and port mirroring, but come with consumer-level hardware, price tag and, as we’ll see, management features.

The TL-SG108E lacks the usual telnet/SSH command-line interface and web interface that you might expect for managed networking equipment. Instead management takes place solely via a Java GUI application - the Easy Smart Configuration Utility (ESCU).

Upon startup, the ESCU goes through a discovery phase to look for Easy Smart switches on your network. After discovery, you have the ability to view some basic information about each switch, change a switch’s network configuration (provided you know the credentials for the switch), or you can log in to the switch in order to manage all of its features. See the TP-Link manual for a thorough run-down of the management utility.

tplink discovery phase

Management traffic

Let’s take a look at what is happening behind the scenes by using Wireshark to examine the network traffic sent by the utility and the switch.

Discovery phase

During the discovery phase, a UDP packet is sent from each of my network interfaces with source port 29809 to the IPv4 broadcast address 255.255.255.255, destination port 29808.

Each switch that receives this discovery probe sends a reply in the form of a UDP packet with source port 29808 to the IPv4 broadcast address 255.255.255.255, destination port 29809.

Notice that there was no need for switch to reply on the broadcast address - it would have known who was looking for it by examining the source IP address and could have replied over unicast rather than announcing its presence to the whole network.

Once the discovery phase has finished, the utility lists the discovered switch and provides two options - I can click the cog icon underneath the “IP Setting” heading which provides a quick way of changing the switch’s management network settings (providing I have the administrative username and password) or I can click the person silhouette icon underneath the “Login” heading which will prompt me for a username and password and, if they are correct, drop me into the main part of the application which allows me to view and modify all of the switch’s features.

Logon and management phase

The traffic which passes over the wire whilst logging in to a switch and exercising the mangement functionality continues in the same vein as the discovery traffic - the destination address for the traffic is always 255.255.255.255, meaning that anyone on the local network will see this communcation in its entirety. This is less than ideal, but at first glance the contents of the traffic is not easily readable.

wireshark traffic encrypted

A quick Google on the topic turned up an excellent blog post from Pentest Parners from mid-2016 which covers these same concerns and, furthermore, they determined that the management traffic is encrypted using a key which is hard-coded in the switch firmware and in the configuration utility.

As that article explains, if you’re managing one of these switches whilst someone is listening elsewhere on the same network, then they get to see everything; the switch’s management credentials, configuration and changes you make to the configuration.

This requires patience on the attacker’s part - they have to be fortunate enough to be capturing traffic whilst the switch is being legitimately managed. Let’s dive a little further and look at the mangement protocol itself to see if there are active attacks we can use against the switch.

The Easy Smart Configuration Protocol (ESCP)

Armed with the crypto key from decompiling the configuration utility, we can begin to examine the payload of the management traffic in its unencrypted form and compare it with the actions we carry out in the utility.

From manually reverse engineering the traffic, and inspecting the decompiled utility, it would appear that all of the packets have a 32 byte header that looks like this:

VV TT SS SS SS SS SS SS CC CC CC CC CC CC QQ QQ
EE EE EE EE LL LL FF FF 00 00 KK KK XX XX XX XX

with the following fields (everything’s big-endian):

  • VV - protocol version (0x01 in my case)
  • TT - packet type
    • 00 for discovery probe
    • 01 for GET request
    • 02 for GET/discovery response
    • 03 for SET/login request
    • 04 for SET response
  • SS SS SS SS SS SS - the MAC address of the switch (filled with zeros for discovery probes)
  • CC CC CC CC CC CC - the MAC address of the management client
  • QQ QQ - a sequence number, the same request/response pairs for correlation
  • EE EE EE EE - error code, (filled with zeroes for OK)
  • LL LL - packet length, including this header
  • FF FF - Fragementation offset, for when requests/responses are too big for one packet
  • 00 00 - Unused, as far as I can tell
  • KK KK - A token of some description, which is refeshed before login and set requests
  • XX XX XX XX - A checksum, which is unused (I’ve only every seen it filled with zeroes)

Following the header is the payload, which is zero or more (Type, Length, Value) tuples (I’m going to call these TLVs), with Type and Length being two bytes each, and Value having a length of, well, Length. Finally, the packet is completed with a byte sequence of FF FF 00 00.

GET requests

To make this more concrete, let’s have a look at a request-reply pair of packets which pass over the wire when we navigate to the “Switching” -> “Port Setting” part of the configuration utility (pictured below).

port setting screen

Request

0000   01 01 66 55 44 33 22 11 aa bb cc dd ee ff 03 ba  ....m..fx$...G..
0010   00 00 00 00 00 28 00 00 00 00 24 78 00 00 00 00  .....(....$x....
0020   10 00 00 00 ff ff 00 00

Here we see a packet type of 01 indicating this is a GET request, of length 0x28, intended for switch with MAC address 66:55:44:33:22:11, from management client MAC address aa:bb:cc:dd:ee:ff, and there is one TLV with type 10 00 (which means switchport configuration) and length zero.

Reply

0000   01 02 66 55 44 33 22 11 aa bb cc dd ee ff 03 ba  ....m..fx$...G..
0010   00 00 00 00 00 7c 00 00 00 00 24 78 00 00 00 00  .....|....$x....
0020   10 00 00 07 01 01 00 01 06 00 00 10 00 00 07 02  ................
0030   01 00 01 06 00 00 10 00 00 07 03 01 00 01 06 00  ................
0040   00 10 00 00 07 04 01 00 01 06 00 00 10 00 00 07  ................
0050   05 01 00 01 06 00 00 10 00 00 07 06 01 00 01 00  ................
0060   00 00 10 00 00 07 07 01 00 01 05 00 00 10 00 00  ................
0070   07 08 01 00 01 05 00 00 ff ff 00 00              ............

Here we see a packet type of 02 indicating this is a GET response of length 0x7c with the same MAC address fields set. Here we see eight TLVs (which unsurprisingly corresponds with the number of ports on the switch) each of type 10 00 and having length 7. Putting them on separate rows and comparing them with the screenshot above, we start to see how each byte of the TLV’s value might correspond with the status of the switchport, as it is shown in the UI.

10 00 00 07 01 01 00 01 06 00 00
10 00 00 07 02 01 00 01 06 00 00
10 00 00 07 03 01 00 01 06 00 00
10 00 00 07 04 01 00 01 06 00 00
10 00 00 07 05 01 00 01 06 00 00
10 00 00 07 06 01 00 01 00 00 00
10 00 00 07 07 01 00 01 05 00 00
10 00 00 07 08 01 00 01 05 00 00
            ^  ^  ^  ^  ^  ^  ^
Port # ─────┘  │  │  │  │  │  │
Enabled ───────┘  │  │  │  │  │
LAG ──────────────┘  │  │  │  │
Speed (configured) ──┘  │  │  │
Speed (actual) ─────────┘  │  │
Flow control (configured) ─┘  │
Flow control (actual) ────────┘

Writing a Wireshark dissector to decrypt the packets and dissect parts of the protocol, we see this better represented visually below.

wireshark dissection

The vulnerability

Notice that the above request did not contain any credentials, unlike SET/login requests which always contain TLVs containing the username and password. That leaves us with two possibilites; there are other authentication mechanisms in play, or the switch discloses its configuration to anyone who asks for it.

Looking back to the structure of the packet header, remember there was a two-byte “token” value. Whenever the configuration utility initiates a SET/login request (which always contains the management credentials), a GET request is made first to refresh this token. Perhaps the switch verifies that the token which accompanies a GET request to “sensitive” information (where sensitive here is defined as any information which the UI would not expose until you’ve logged into the switch) has been authenticated?

To test this, we send a copy of the request (from another host on the network which has had no management interactions with the switch up until now), with the token set to a random value. The switch replies just the same as it did with the previous, authentic request.

So we have ourselves a information disclosure vulnerability - anyone on the network can ask the switch for its various configuration parameters without authentication. This includes the configuration and status of the switchports, names and tags for configured VLANs and member ports, QoS settings, port mirror settings and much more.