Client fingerprinting is broken and no one seems to care

Client fingerprinting, in my opinion, is one of those features that many people don’t think about until they either need it, want it, or it’s broken. It’s not as sexy as other Wi-Fi security related topics such as 802.1X or micro segmentation and it’s certainly not going to prevent a client from operating correctly on the network if it’s not available (or can it?). However, it does help provide insight into your Wi-Fi client base which can be valuable in terms of knowing what device or devices are popular and making sure your Wi-Fi supports them well. Additionally, it is possible to tie access controls to clients by their device type which can affect what they are able to do on the network. With that said, it’s probably worth knowing how client devices are identified from their manufacturer down to the OS version and more importantly, the methods your Wi-Fi vendor uses to identify them. In this post, I’m going to discuss how client fingerprinting is done in general, how RUCKUS does it, and how one method of fingerprinting that we use today is changing due to security concerns.

Traditionally, fingerprinting has leveraged globally unique MAC Addresses (almost impossible today thanks to MAC randomization) or DHCP as a best effort to identify a client’s vendor and/or OS. When a client joins a DHCP-enabled network, it sends DHCP Discover and Request packets and in them they request a list of items called the “Parameter Request List” or Option 55 that helps to configure themselves properly on the network. Some of those list items might even be familiar to you… Subnet mask, router (aka default gateway), domain name servers, or domain name ring a bell to anyone? Yep, clients request those items and more during the DHCP process. And just so you are aware, there are other options that a client might include that can be leveraged for identification like Option 12 (Hostname), Option 60 (Vendor Class Identifier), or Option 61 (Client Identifier), but I’m going to primarily focus on Option 55. As a side note, Apple devices do not include Option 60 so it will not help you in all scenarios.

You might be wondering how this helps with fingerprinting if every client is asking for the same or similar information? Great question! Most vendors will use very specific options in a very specific order and those options may or may not change with every new version of OS that is released. For example, Windows Vista and Windows 7 used the same list and order (1,15,3,6,44,46,47,31,33,121,249,43). As another example, here are the items requested by an Apple device running macOS 10.15 aka Catalina:

Now let’s look at a request from an Apple device running macOS 11 (Big Sur):

It can be hard to catch, so I highlighted the difference in orange. Big Sur requests the additional “DHCP Captive-Portal” item (114) right below “Domain Name”. Let’s try one more for fun… How about from a beta of macOS 12 (Monterey)?

In addition to item 114, it’s also requesting item 108 “Removed/Unassigned” right before it. By using the specific list of requested items and the order they are in, you can formulate an intelligent guess of what vendor and OS a device is running. But it’s still just that, a guess. And look how easy it was to figure that out… An attacker could manipulate their DHCP packets to make their device look like any other if they wanted to; especially if they knew they could get access to different resources if your policies are tied to device types. Additionally, what if two different devices are requesting the same items? Sure, there’s also Option 60 and 61 that can be leveraged, but with some manufacturers like Apple not using Option 60, it makes the guess that much tougher. Fortunately, there are other options available to aid in fingerprinting, but most Wi-Fi vendors have settled on either DHCP or a combination of DHCP and HTTP for their fingerprinting capabilities.

Up until SmartZone 5.2, RUCKUS only relied on DHCP for fingerprinting which as you’ve now seen, is flawed. In addition to DHCP, SmartZone 5.2 began to use HTTP for fingerprinting as well. It’s important to make that distinction clear. HTTP, not HTTPS, which means the packet was sent in cleartext. If the controller or AP processes one of these cleartext HTTP packets from a client device, it will use information from the included User-Agent (UA) string which is a field in the HTTP header that every web browser sends to identify the client’s OS and web browser to a receiving web server. DHCP with the use of the options like 55, 60, and 61 can still be leveraged to initially identify the vendor and device type, but HTTP (if detected) will take precedence in terms of identifying the OS. For those of you who might be unfamiliar with the user-agent string, here’s what it looks like from within Wireshark:

Chrome in macOS Catalina 10.15.7

Firefox in macOS Catalina 10.15.7

Safari in macOS Catalina 10.15.7

As you can see by the screen shots above. Each browser’s UA string is slightly different, but they all state that the device is an Intel Mac running 10.15. An easy way to see the UA string being sent by your device and web browser is to visit In the screen shot below (Thanks Darrell!), it appears that Apple isn’t capping the UA string for iOS 15 by default just yet, but from what I understand (e.g. Firefox is already doing this in Windows) it is coming to all major browsers on all major OSes so be ready! 

This issue caught my attention when a colleague raised the question about why our platform (SmartZone) was not classifying newer versions of macOS (11 and 12 beta) correctly; a MacBook Pro running Big Sur (11.5.7) was being classified as Catalina (10.15.7). The finger was initially pointed towards our software developers to get the client databases updated, but the more I dug into this issue, the more I realized it wasn’t their fault. This behavior was planned and operating exactly how the major web browser companies and security folks planned it.

Back in 2020, major players like Apple, Google, and Mozilla started to discuss and prepare for capping the UA string in their respective browsers. The reason was two-fold: They wanted to improve privacy for users where clients were passively being fingerprinted based on the UA string and things were starting to break across the web as the UA string continued to grow longer and more complex. Not to mention, minority browsers claiming that their browsers are unfairly treated can lie in their UA strings to mimic the client experience of major browsers. But they couldn’t just remove the UA string, because too many servers on the web depended on it. In fact, the plan was to cap it at “11” for macOS devices to support Big Sur, but even that broke compatibility on websites that were expecting to see version 10 so they settled on the last release of Catalina, 10.15.7. Here’s an example of how seeing the UA string in a plain-text HTTP packet can change the identification of devices in SmartZone:

My MBP is correctly identified correctly as a laptop running macOS Catalina (10.15.7) after visiting the unencrypted website, My iPad Pro running iPadOS 14.8 is identified as a smart phone running iOS before visiting the website since DHCP was the only method used and iOS/iPadOS fingerprints match (1,121,3,6,15,114,119,252)

After visiting, the iPad’s identification changes, but is still incorrectly identified as a laptop running macOS 10.15.6 due to the UA string sent by Safari (desktop versions of websites are requested by default)

By disabling “Request Desktop Website” in Settings -> Safari, the iPad is now correctly identified as a Tablet with the correct version of iPadOS (iOS) after visiting

So is client fingerprinting dead? With DHCP being somewhat unreliable and HTTP effectively rendered useless, it seems so, right? For me, the right answer is it depends. The Web Platform Incubator Community Group introduced a plan to still allow for fingerprinting, but in a manner that is active vs passive and a bit more secure using something called User-Agent Client Hints (UA-CH). This allows a client to initially only send a subset of the information found in the typical UA string but allows the server to request for more information as needed. Sounds great. The problem is, this only works over TLS, meaning the HTTP headers that are sent back and forth between the client and server will be encrypted and unable to be seen unless a device is acting as a proxy server for the client’s connection. This is unlikely to happen with wireless controllers or APs so while this appears to fix their problem, it doesn’t fix ours. So where do we go from here? Do we go back to just relying on MAC OUI and DHCP as a best effort way of identifying devices and ignore the UA string? Should we even be using device type as a means of providing specialized network access or policy? Probably not, because it wasn’t foolproof even with HTTP in the mix as I illustrated above. I found this problem rather interesting, but I haven’t seen much mentioned about this within the Wi-Fi community so I’m genuinely curious what everyone’s thoughts are about this. Is it just a big “I don’t care.” or is there more to this? Reach out on Twitter to start a conversation!

Ps. Special thanks to Darrell DeRosia, Dan Jones, and Jim Palmer

Sources: Google discussion about capping the UA stringMozilla discussionSafari discussionImproving user privacy and developer experience with User-Agent Client HintsClient Hints Infrastructure