反爬虫 SSL TLS 指纹识别和绕过 JA3 算法
date
Jul 13, 2022
Last edited time
Mar 27, 2023 08:47 AM
status
Published
slug
反爬虫SSL_TLS指纹识别和绕过JA3算法
tags
scraper
summary
转载
type
Post
Field
Plat
0x00 前言
有时候会发现一种情况,用正常浏览器可以访问,但是用脚本或者挂一下代理访问 https 的网站就直接 405 禁止访问了。
这种情况就有可能是 识别了你的 TLS 指纹,这种情况换随机 UA 都是没什么用的。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F9268acb7-bf67-46fc-8dbb-9f932d28c51d%2F1317c485-bfeb-4b65-99ad-63e7d617b35d.png?table=block&id=65f112c7-cde6-4ea0-9e88-13f7da95ff62&cache=v2)
查阅资料之后,发现应该是 waf 识别你的 TLS 指纹,标记为恶意直接禁止了,其中识别的算法主要是利用 JA3 和 JA3S 实现 TLS 指纹识别功能,所以学习了一下。
0x01 实际测试一下
测试代码
第一步,我们就看看我们的特征是什么,测试一下到底改 hearder 方法行不行。代码是测试代码,主要就是重复发包看一下特征。
主要有三种:修改过 tls 的,原生的,改 header 头的
测试结果如下
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F2cf06066-21ea-437f-8d3e-f05a21e38b8b%2Fca271b0a-f6ee-440b-8744-f5332fcc121a.png?table=block&id=29060883-5e43-4c96-9174-a4fe0592d972&cache=v2)
- 也就是说我们修改 hearder 这个东西里面字段(User-Agent,Referer, 各种东西)其实都不会影响这个指纹,因为他是计算 SSL 中 TLS 得出的
- 用 python 的 requests 库发包,ja3_hash 一直都是一个固定值
- 8896468359a279a05de2651c5021ac6f
- 所以我们可以使用 TLS Client Hello 数据包中的详细信息对客户端应用程序进行指纹识别。我们按照这个作为规则,就可以直接禁止调 python 的原生脚本
百度之后发现这个检测算法,叫做
JA3算法
0x02 JA3 算法
JA3 就是一种在线识别 TLS 客户端指纹的方法
JA3 算法收集了 SSL 请求里面的信息,包括但不限于 SSL/TLS 版本,
Cipher Suites
数量,浏览器扩展列表,elliptic curves
等等。![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F1f2603aa-9621-409d-8251-83b30c5e8fbc%2Fc0e4245f-1234-4e9e-9d5e-18f148aff0f7.png?table=block&id=bf04902b-d279-444b-bcf9-9205a93b0fb4&cache=v2)
这些字段的顺序如下所示:
TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats
例如:
如果 Client Hello 数据包中没有 TLS 扩展(TLS Extensions),则这些字段的值为空。
然后,会计算这些字符串的 MD5 哈希值,以生成易于使用和共享的长度为 32 字符的指纹。它们就是 JA3 TLS 客户端的指纹。
对于每个客户端来说,总是以相同的方式进行相应,所以 JA3 指纹就是唯一的。
0x03 wireshark 抓包
正常浏览器可以访问 https://ja3er.com/json 这个站点,查看自己的 ja3hash,可以看到每个浏览器都不一样的
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe3dcfca1-d1d7-47c5-b02e-96d1f5c270f3%2Fa1ae9b75-5680-45ee-8d3d-4dc924fc6c07.png?table=block&id=ac9c452c-11fa-4f07-a996-da02644c18c1&cache=v2)
下面是具体的 wireshark 抓包,查看一下具体的细节
Chrome
python requests 库
Burp
compare 对比一下
发现加密套件 Cipher Suites 相差特别多
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F68d6ba81-8b3e-444f-b229-0f77c89e2747%2F8a6ce24c-bd58-4b27-945e-5e96c0f6dfe1.png?table=block&id=5be87d7a-f2c2-445a-874e-73e46ab08139&cache=v2)
0x04 问题解决
作为脚本小子,当让得 bypass 了这个,要不以后啥也干不了了,暂时找到了两种方法
- 改自己的代码逻辑,
- 直接修改底层的依赖包
方法一、修改上层代码
这个是参考网上的一段代码,大家可以自行修改一下。
方法二、修改底层的依赖 requests 包
还有一个问题,代码写多了,你不可能每个代码都改一下,那不得累死,除非你写之前就把发送数据包的函数封装好了,改一个就行,要不最好的方法就是把底层的依赖包直接改了。
但是其实,Requests 其实是对 urllib3 的一个封装,所以关键的还是在 urllib 库
debug 找到位置:
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F6f82a8d5-aba1-4b70-be10-f3e253b1e6eb%2Fbf4f83e3-5325-4447-b75d-ad4ebaae94c1.png?table=block&id=255abc97-b235-4d88-8214-480f522602e2&cache=v2)
这个是原版的的加密库
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7f2500cc-6a42-4435-bca0-fb43dd069f4b%2F2283275f-b435-483e-99c9-0ca4a9a1acc4.png?table=block&id=48839f56-6441-4e8c-be0f-920b4f78145d&cache=v2)
根据原理,是按照字段的顺序先算一遍,再 hash 计算一下
所以,为了最小程度变更而且不影响代码,我们只要吧 Ciphers 里面的加密算法调换一下顺序就好了。
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F1e03645c-55e7-4a42-b4fc-3f76d0c21262%2Ff31617cf-e71b-4399-8dbb-1219e6359558.png?table=block&id=808e117a-47fe-410a-b30f-ab5b5a307b6e&cache=v2)
再用代码测试一下
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Faf492403-9b9f-410b-9f0e-72fdb05600e6%2F2254527e-ee04-4880-81b1-d96058ff2670.png?table=block&id=f1b465b4-a06f-4cac-b7a3-4d2bbfef0c81&cache=v2)
0x05 总结
根据规则其实还有好多方法,只要你熟悉协议了解原理可以慢慢改,我这种不太懂的,就找一个最简单的方法,能实现就好了,太复杂怕把自己绕进去。