首页 > 其他分享 >14-TLS指纹

14-TLS指纹

时间:2024-02-11 10:11:41浏览次数:32  
标签:TLS 14 AESGCM res 指纹 https requests com

day14 TLS指纹校验原理和绕过

浏览器可以正常访问,但是用requests发送请求失败。

后端是如何监测得呢?为什么浏览器可以返回结果,而requests模块不行呢?

https://cn.investing.com/equities/amazon-com-inc-historical-data

image-20231102222853489

image-20231102222951995

1.指纹校验案例

1.1 案例:ascii2d

https://ascii2d.net/

image-20231102152118149

image-20231102152223565

import requests

res = requests.get(
    url="https://ascii2d.net"
)

print(res.text)
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <title>Just a moment...</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
   ...
</html>

1.2 案例:investing

https://cn.investing.com/equities/amazon-com-inc-historical-data

image-20231102222853489

image-20231102222951995

import requests

res = requests.get(
    url="https://cn.investing.com/equities/amazon-com-inc-historical-data",
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    }
)
res.encoding = 'utf-8'
print(res.text)

1.3 案例:yuanrenxue

image-20231102152648185

image-20231102152734717

import requests

res = requests.get(
    url="https://match.yuanrenxue.cn/api/match/19?page=1"
)

print(res.text)

2.TLS指纹

如今几乎所有平台通信都是基于Https的协议,而无论基于什么工具去发送Https请求时,都需要基于TLS/SSL先建立两端安全的通信(握手),建立后再进行数据传输。

TLS的握手阶段,客户端会向服务端发送 Client Hello 数据包,在数据包内的JA3就是指纹信息(基于电脑的TLS版本+内置算法等计算出来的字符串),并且该值不会随着请求头修改、代理等发生变化。所以,某个网站的后台就会去读取TLS客户端的JA3指纹,如果是非正常指纹,禁止访问。例如:

  • requests请求

    requests==2.31.0
    urllib3==2.0.7
    
    [JA3 Fullstring: 771,4866-4867-4865-49196-49200-159-52393-52392-52394-49195-49199-158-49188-49192-107-49187-49191-103-49162-49172-57-49161-49171-51-157-156-61-60-53-47-255,0-11-10-16-22-23-49-13-43-45-51-21,29-23-30-25-24,0-1-2]
    
    [JA3: bc29aa426fc99c0be1b9be941869f88a]
    
    固定,所以后端API可以禁止此指纹。
    
  • 浏览器请求

    [JA3 Fullstring: 771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,11-18-27-35-16-51-10-23-5-43-65281-65037-0-17513-13-45,29-23-24,0]
    
    [JA3: 5ae2fe79293ec63d585f3f987cf69d01]
    
    谷歌浏览器的JA3会变化。
    

扩展:有些网站专门收录ja3黑名单。

https://sslbl.abuse.ch/ja3-fingerprints/
https://sslbl.abuse.ch/blacklist/sslblacklist.csv
https://github.com/salesforce/ja3/blob/master/lists/osx-nix-ja3.csv
https://ja3er.com/getAllUasJson
https://ja3er.com/getAllHashesJson

2.1 查看指纹

想要快速查看自己的TSL指纹信息:https://tls.browserleaks.com/json

image-20231102160720074

import requests

res = requests.get('https://tls.browserleaks.com/json')
print(res.text)

image-20231102160648459

其他网站还有:

https://tls.browserleaks.com/json
https://tls.peet.ws/
https://tls.peet.ws/api/all

2.2 Wireshark

基于Wireshark抓包并筛选出Client Hello数据包,去内部查看:

1.下载安装

下载并安装Wireshark https://www.wireshark.org/download.html

image-20231102162717583

2.抓网卡

打开Wireshark,选择要抓包监测的网卡,选择你上网使用的那个网卡。

image-20231102162114984

3.筛选IP

筛选目标IP ip.dst_host==146.56.195.149

image-20231102162435891

image-20231102162148914

4.数据包

用浏览器或用requests发送请求,就可以监测到网络请求,然后找到 Client Hello数据包,就可以看到相关指纹信息。

image-20231102154253441

2.3 ja3

image-20231102165413527

[JA3 Fullstring: 771,4866-4867-4865-49196-49200-159-52393-52392-52394-49195-49199-158-49188-49192-107-49187-49191-103-49162-49172-57-49161-49171-51-157-156-61-60-53-47-255,0-11-10-16-22-23-49-13-43-45-51-21,29-23-30-25-24,0-1-2]

[JA3: bc29aa426fc99c0be1b9be941869f88a]

关于加密相关的值:

  • JA3 是对 JA3 Fullstring进行md5加密的结果。

  • JA3 Fullstring是由五段组成

    JA3 gathers the decimal values of the bytes for the following fields in the Client Hello packet; 
    	- SSL Version,
    	- Accepted Ciphers
    	- List of Extensions
    	- Elliptic Curves
    	- Elliptic Curve Formats
    It then concatenates those values together in order, using a "," to delimit each field and a "-" to delimit each value in each field.
    
    JA3 为客户端发送的clienthello 数据包中的以下字段收集字节的十进制值: SSL Version, Accepted Ciphers, List of Extensions, Elliptic Curves, and Elliptic Curve Formats(SSL 版本、接受的密码、扩展列表、椭圆曲线和椭圆曲线格式)。然后它将这些值按顺序连接在一起,使用“,”分隔每个字段,使用“-”分隔每个字段中的每个值。
    
    https://github.com/salesforce/ja3
    
    SSLVersion, Cipher, SSLExtension, EllipticCurve, EllipticCurvePointFormat
    
    第1个值:771                                   表示SSL版本,即:TLS 1.2(0x0303),0x0303转换为10进制就是771
    
    第2个值:4866-4867-4865-49196-49200-159-52393-52392-52394-49195-49199-158-49188-49192-107-49187-49191-103-49162-49172-57-49161-49171-51-157-156-61-60-53-47-255        表示TLS客户端支持的加密套件。
    
    第三个值:0-11-10-16-22-23-49-13-43-45-51-21    表示支持的 TLS 扩展
    
    第四个值:29-23-30-25-24                        表示支持的支持的椭圆曲线(ECC加密算法)
    
    第五个值:0-1-2                                 表示支持的椭圆曲线格式
    

1.SSLVersion

771

将0x0303转换为10进制就是771

image-20231102171445727

2.Cipher

4866-4867-4865-49196-49200-159-52393-52392-52394-49195-49199-158-49188-49192-107-49187-49191-103-49162-49172-57-49161-49171-51-157-156-61-60-53-47-255

将算法套件的十六进制表示,转换成十进制,然后再凭借起来。

image-20231102171555206

3.SSLExtension

0-11-10-16-22-23-49-13-43-45-51-21

SSL中所有的扩展对应的数字

image-20231102174433762

4.EllipticCurve

29-23-30-25-24

将supported_groups对应的十六进制转换成十进制。

image-20231102173836479

5.EllipticCurvePointFormat

0-1-2

ec_point_formats转换转换十进制。

image-20231102174113014

3.突破指纹

理解TLS中ja3生成机制后,绕过的思路也就有了:requests请求时,改变 ja3 string得内容,生成合法的的ja3指纹

3.1 【PY】requests【案例3】

requests在发送请求时,内部依赖urllib3实现。

pip install urllib3==1.26.15
pip install urllib3==1.26.16
pip install urllib3==2.0.7

image-20231102182216117

自定义 ciphers实现生成非默认ja3

方式1:

import requests
import urllib3

urllib3.util.ssl_.DEFAULT_CIPHERS = ":".join([
    # "ECDHE+AESGCM",
    # "ECDHE+CHACHA20",
    # "DHE+AESGCM",
    # "DHE+CHACHA20",
    # "ECDH+AESGCM",
    # "DH+AESGCM",
    # "ECDH+AES",
    "DH+AES",
    "RSA+AESGCM",
    "RSA+AES",
    "!aNULL",
    "!eNULL",
    "!MD5",
    "!DSS",
])

res = requests.get(
    url="https://tls.browserleaks.com/json",
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    }
)
res.encoding = 'utf-8'
print(res.text)

方式2:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context


class MineAdapter(HTTPAdapter):
    CIPHERS = ":".join(
        [
            "ECDHE+AESGCM",
            "ECDHE+CHACHA20",
            "DHE+AESGCM",
            "DHE+CHACHA20",
            "ECDH+AESGCM",
            "DH+AESGCM",
            "ECDH+AES",
            "DH+AES",
            "RSA+AESGCM",
            "RSA+AES",
            "!aNULL",
            "!eNULL",
            "!MD5",
            "!DSS",
        ]
    )

    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super().init_poolmanager(*args, **kwargs)

    def proxy_manager_for(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super().proxy_manager_for(*args, **kwargs)


session = requests.Session()
session.headers.update({
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
})
session.mount("https://", MineAdapter())

res = session.get("https://tls.browserleaks.com/json")
res.encoding = 'utf-8'
print(res.text)

用此方法,可以过案例3的TLS校验机制,例如:

import requests
import urllib3

urllib3.util.ssl_.DEFAULT_CIPHERS = ":".join([
    # "ECDHE+AESGCM",
    # "ECDHE+CHACHA20",
    # "DHE+AESGCM",
    # "DHE+CHACHA20",
    # "ECDH+AESGCM",
    # "DH+AESGCM",
    # "ECDH+AES",
    "DH+AES",
    "RSA+AESGCM",
    "RSA+AES",
    "!aNULL",
    "!eNULL",
    "!MD5",
    "!DSS",
])

res = requests.get(
    url="https://match.yuanrenxue.cn/api/match/19?page=1",
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    }
)
res.encoding = 'utf-8'
print(res.text)

注意:Python层得TLS是基于底层openssl对外提供的方法,而openssl暴漏给Python只能通过修改 ciphers 来修改ja3指纹,无法支持修改 SSLExtension, EllipticCurve, EllipticCurvePointFormat

3.2 【PY】curl_cffi【案例1+2+3】

https://pypi.org/project/curl-cffi/#description

  • curl是一个可以发送网络请求的工具。
  • curl-impersonate是一个基于curl基础上进行开发的一个工具,可以完美的模拟主流的浏览器。
  • curl_cffi,是套壳curl-impersonate,让此工具可以更方便的应用在Python中。
pip install curl-cffi
from curl_cffi import requests

res = requests.get(
    # url="https://ascii2d.net/",
    # url="https://cn.investing.com/equities/amazon-com-inc-historical-data",
    url="https://match.yuanrenxue.cn/api/match/19?page=1",
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
    },
    impersonate="chrome101",
)
print(res.text)

3.3 【Go】CycleTLS 【案例1+2+3】

关于Golang环境和基础入门教程可以参考:

课件:https://www.5xclass.cn/wiki/detail/4/0/
视频:https://www.bilibili.com/video/BV1u5411W79w/

github上有一个基于Golang开发的开源模块CycleTLS ,可以更靠近底层去实现定制ja3指纹,直接自定义ja3 fullstring

https://github.com/Danny-Dasilva/CycleTLS

image-20231103184851991

go get github.com/Danny-Dasilva/CycleTLS/cycletls 
package main

import (
	"github.com/Danny-Dasilva/CycleTLS/cycletls"
	"log"
)

func main() {

	client := cycletls.Init()
	
    // https://ascii2d.net/
    // https://cn.investing.com/equities/amazon-com-inc-historical-data
    // https://match.yuanrenxue.cn/api/match/19?page=1
	response, err := client.Do("https://tls.browserleaks.com/json", cycletls.Options{
		Body:      "",
		Ja3:       "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0",
		UserAgent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0",
	}, "GET")
	if err != nil {
		log.Print("Request Failed: " + err.Error())
	}
	log.Println(response)
}

标签:TLS,14,AESGCM,res,指纹,https,requests,com
From: https://www.cnblogs.com/fuminer/p/18013195

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (198)-- 算法导论14.3 6题
    六、用go语言,说明如何来维护一个支持操作MIN-GAP的一些数的动态集Q,使得该操作能给出Q中两个最接近的数之间的差值。例如,Q=(1,5,9,15,18,22),则MIN-GAP返回18-15=3,因为15和18是Q中两个最接近的数。要使得操作INSERT、DELETE、SEARCH和MIN-GAP尽可能高效,并分析它们的运行时间。文心一言,代......
  • 力扣递归 两道简单题合成一道中等题之148. 排序链表
    递归归并排序,先找到终点,再合并两个链表 给你链表的头结点 head ,请将其按升序排列并返回排序后的链表。 示例1:输入:head=[4,2,1,3]输出:[1,2,3,4]示例2:输入:head=[-1,5,3,4,0]输出:[-1,0,3,4,5]示例3:输入:head=[]输出:[]/** *Definitionforsingl......
  • Educational Codeforces Round 145 (Rated for Div. 2)C. Sum on Subarrays(构造)
    很意思的一道构造题题意:给一个\(n、k\),让构造长度为n的数组满足,子数组为整数的个数为k个,负数的为\(k-(n+1)*n/2\),每个数的范围为\([-1000,1000]\)这种构造题可以考虑就是前一段可以一直用一样的、最小的。我们观察可以发现\(k+k-(n+1)*n/2=(n+1)*n/2\)也就是所有子数组......
  • 文心一言 VS 讯飞星火 VS chatgpt (197)-- 算法导论14.3 5题
    五、用go语言,对区间树T和一个区间i,请修改有关区间树的过程来支持新的操作INTERVALSEARCH-EXACTLY(T,i),它返回一个指向T中结点x的指针,使得x.int.low==i.low且x.int.high==i.high;或者,如果不包含这样的区间时返回T.nil。所有的操作(包括INTERVAL-SEARCH-EXACTLY)......
  • ABC 314
    F每次相当于创建一个包含\(p_i,q_i\)各自所在集合的点的大点\(u\),然后\(u\)向\(p_i,q_i\)各自所在集合连边,边权就是胜率。连完之后求每个点到根结点(\(\{1\simn\}\))的路径边权和。G定义\(L_i\)为杀至少\(i\)个怪物至少需要多少护身符。如果求出\(L_0\simL_n\),可......
  • 【CPL-2023】W14笔记-程序结果、预处理与I/O
    有趣的预编译编写大型程序头文件:变量的声明,函数的声明,宏的定义,预编译指令include库函数include<xx.h>找库函数的路径include自己的头文件include"xx.h",先找当前目录gcc--verbosemain.cgcc-I.include当前目录头文件的重复包含标准头文件结构#ifndef......
  • Vision Pro 5 月将在中国区发售;全球科技大厂 1 月已裁员 32000 人丨RTE 开发者日报 Vo
      开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(RealTimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑......
  • Go语言精进之路读书笔记第14条——了解map实现原理并高效使用
    14.1什么是mapmap对value的类型没有限制,但是对key的类型有严格要求:key的类型应该严格定义了作为“==”和“!=”两个操作符的操作数时的行为,因此func、map、slice、chan不能作为map的key类型。map类型不支持“零值可用”,未显式赋初值的map类型变量的零值为nil。对处于零值状态的......
  • 3 return2/14
    #include<bits/stdc++.h>usingnamespacestd;intmain(){intn;while(cin>>n){if(n==0)return0;intans=0,cnt=0;vector<int>a(n);for(auto&num:a){cin>>num;......
  • CF1408F Two Different 题解
    解题思路先考虑如何将一堆数变为相同的。显然,这里有一个条件\(n=2^k,k\in\mathbbZ\),证明如下:每次操作只能将两个数变为相同的,那么一个数在使得其他数变为相同数的操作中(我们不妨将所有数进行这种操作称为一轮操作),一个数最多被使用一次;按照错位操作,即第一轮\(1\)和\(2\)......