Fighting TLS Fingerprinting with Node.js
httptoolkit.tech
httptoolkit.tech
It is far more likely in practice that 3~5 RSA or ECC base PKI suites would comprise the majority of HTTPS sessions.
EDIT: I found a 2018 survey of 1,000,000 websites and these were the top 10 ciphersuites, far from the quadrillion combos the OP computed.
ECDHE-RSA-AES256-GCM-SHA384 147985
ECDHE-RSA-AES128-GCM-SHA256 127964
ECDHE-ECDSA-AES128-GCM-SHA256 41043
ECDHE-RSA-AES256-SHA384 15400
DHE-RSA-AES256-GCM-SHA384 4326
ECDHE-RSA-AES256-SHA 3231
DHE-RSA-AES256-SHA 2484
0000 2194
AES256-SHA 2113
AES128-SHA 1855
https://scotthelme.co.uk/alexa-top-1-million-analysis-februa...Yes, most aren't used for many real sessions, but they're all still supported and available for fingerprinting. The selected cipher isn't relevant.
The quadrillion total meanwhile it the total number of _permutations_ not the number of ciphers.
In local testing, every single client (e.g. curl, Firefox, chrome) I've seen sends between 15 to 35 options in every client hello, which already gives you a huge number of possible permutations, though you couldn't really reorder them completely freely without real security implications.
As in the article, the extensions are more interesting for increasing permutations though, since order there really is totally arbitrary.
TLS: 1
Ciphers: A, B, C
Extensions:
ExtensionX: ...
ExtensionY: ...
ExtensionZ: ...
That gets converted into a string like "1-A,B,C-X,Y,Z", and then hashed with MD5 to get a value like "41b2054b6a0a7549fa963b232226f6ae". For every single server you talk to, those values will be the same, we'll get the same fingerprint, and so this distinctively identifies TLS connections made by this client.Another client might instead send:
TLS: 1
Ciphers: C, B, A
Extensions:
ExtensionX: ...
ExtensionY: ...
ExtensionZ: ...
That becomes a string like "1-C,B,A-X,Y,Z", which gets hashed to a fingerprint like "ae76e4566b036882147de2f7feddad4a". That gives us a totally different unique id, with the same ciphers but in a different order.(This is pseudocode of course - the actual fingerprints have a few more params and use the number ids for each cipher and extension instead of strings, but it's equivalent)
Here, with 3 ciphers in two different orders, we've seen two different fingerprints already. With those three ciphers alone, there's actually 6 (3 factorial) possible permutations - i.e. a client could order those ciphers any one of 6 different ways, and each ordering has a different fingerprint.
If you have 4 ciphers, there's 24 possible orderings, 6 gives 720, 10 gives 3.6 million, and this goes up very rapidly, so that for a more realistic set of 20 ciphers there's 2 * 10^18 possible orderings, each one of which gives a unique fingerprint, even before we start talking about extension order.
Does that make more sense? The full algorithm is here: https://github.com/salesforce/ja3#how-it-works
Way back in the days around y2k many network stacks had poor or no randomization of some parameters that produced some neat looking plots: https://lcamtuf.coredump.cx/newtcp/
After reading the post, that's what I'm going to play with next time I run into this. I suspect duplicating will be fine in almost all environments, and by picking one way way down in the preference list to duplicate, I suspect you can increase the chances that there's nothing in the chain that will even have an opportunity to error based on the duplicated cipher preference. I tried this against the website quoted in the article and it worked without problem.
I doubt that's happening today, but I suspect it will very quickly if duplicate ciphers become commonplace.
Actually reordering ciphers meanwhile definitively changes the hash, so there's nothing they can do in the general case at least, and there's a reasonably large number of acceptable non-duplicate orderings available to choose from.
Duplicating ciphers is a good technique that's definitely worth investigating too, but it has its limitations, and it's not a silver bullet.
See [1], e.g. In security, simplicity is often but not always by itself a win.
Great article, btb, really appreciated the real world examples.
If however you can predict the number, you can create a connection without being able to receive packets from the server.
So if for instance an administrator has setup their machine to accept connections to an insecure service only from a specific IP address, you can now set up such a connection without actually controlling the IP address.
the only online demos of this i know of are: http://witch.valdikss.org.ru/ and https://bot.incolumitas.com
i believe the WITCH site is based on p0f (https://lcamtuf.coredump.cx/p0f3/)
i know some people have custom patches to the linux kernel to make it look like a different operating system in order to work around bot detection.
A particularly useful anti-bot feature is to fingerprint TLS connections by things like cipher order and available signatures (if you're willing to switch back to TLS 1.2). This way, you can easily detect the difference between browsers and bots, even if all the request headers match . If you're fine with blocking people behind middleboxes or proxies then it can be a simple yet useful fingerprinting technique.