指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(1)

这是关于网络指纹识别的两部分系列的第二部分

HTTP/2 指纹识别

和tls指纹类似也是一种 Web 服务器可以依赖指纹来识别哪个客户端。

例如,它可以识别浏览器类型和版本,或者是否使用了脚本(你是真实浏览器啊还是ScriptBoy?)。

该方法依赖于 HTTP/2 协议的内部结构,与其更简单的前身 HTTP/1.1 相比,这些内部结构鲜为人知。

在这篇文章中,我将首先简要介绍 HTTP/2协议,然后详细介绍我们可以协议的哪些参数来识别你究竟谁(what are you)!

与HTTP/1.1相比

使用HTTP/1.1协议,客户端向服务器发送文本请求(通常使用 TLS 加密)默认情况下,Chrome 的请求如下所示:

GET / HTTP/1.1 Host: www.wikipedia.org sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36 Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9

User-Agent包含客户端的确切版本,虽然可用于识别客户端。但是很容易被任何 http 库或命令行工具伪造(地球人都知道)!

HTTP/2 简介

HTTP/2 是 HTTP 协议的主要修订版,从 2015 年左右开始出现。现在大约一半的网站使用 HTTP/2

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(2)

image

基本上所有流行的网站都默认使用它!

如何看服务端使用的是否是http2协议呢?

在chrome上看是这样的

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(3)

image

在Firefox上看是这样的

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(4)

HTTP/2 的主要目标是提高性能

然而,HTTP 协议的应用程序语义没有改变:它仍然由熟悉的请求/响应模型组成,包括 URI、HTTP 方法、HTTP 标头和状态码。

Frames and Streams

HTTP/2 是一种二进制协议,与文本 HTTP/1.1 不同。HTTP/2 中的消息由帧组成,有十种不同用途的帧。帧始终是流的一部分。

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(5)

Stream都是有编号的,从0开始

如上图:编号为0的Stream包含如下

然后是编号开始递增,代表了客户端给服务端发送的实际请求,如上图为1的Stream:

使用 HTTP/2 进行客户端指纹识别研究http2协议的工具

这里推荐使用nghttpd,它可以很方便的创建一个http2协议的webserver。最关键的是,让客户端请求的时候它能够直观的把每一帧都给打印出来(下面会给大家演示) 我将它安装在wsl的ubuntu机器上,还得自建一个证书,这里我遇到了一点坑, 避坑指南请看我写的(wsl创建证书让chrome浏览器识别):

下面就是如何使用nghttpd跑h2协议server

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(6)

我这里分别使用如下客户端来测试

1. SETTINGS

上面介绍到这是客户端发送的第一帧,里面有一些特殊配置

Chrome

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(7)

image

recv SETTINGS frame <length=24, flags=0x00, stream_id=0> [SETTINGS_HEADER_TABLE_SIZE(0x01):65536] [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):1000] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):6291456] [SETTINGS_MAX_HEADER_LIST_SIZE(0x06):262144]

Firefox

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(8)

image

recv SETTINGS frame <length=18, flags=0x00, stream_id=0> [SETTINGS_HEADER_TABLE_SIZE(0x01):65536] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):131072] [SETTINGS_MAX_FRAME_SIZE(0x05):16384]

CURL

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(9)

image

recv SETTINGS frame <length=18, flags=0x00, stream_id=0> [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):1073741824] [SETTINGS_ENABLE_PUSH(0x02):0]

PYTHON

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(10)

image

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(11)

image

recv SETTINGS frame <length=36, flags=0x00, stream_id=0> [SETTINGS_HEADER_TABLE_SIZE(0x01):4096] [SETTINGS_ENABLE_PUSH(0x02):0] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [SETTINGS_MAX_FRAME_SIZE(0x05):16384] [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_MAX_HEADER_LIST_SIZE(0x06):65536]

很明显,根据测试,在SETTINGS Frame帧里面配置, 不同的客户端设置的种类和值都是不同的,这使得很容易区分是否是浏览器, 而且这个配置不容易控制,可以用于指纹识别!

WINDOW_UPDATE

HTTP/2 实现了一种流控制机制。流量控制为接收方提供了在每个流的基础上调节流量的机制。使用WINDOW_UPDATE大小来实现的

默认窗口大小由SETTINGS帧里面的 SETTINGS_INITIAL_WINDOW_SIZE中的值控制, 参考上方测试,可以看到 Chrome 使用 6MB (6291456) 而 Firefox 使用 128KB (131072)

当客户端接收数据时,它可以使用WINDOW_UPDATE框架来调整窗口大小,从而增加其窗口大小。

Chrome

recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0> (window_size_increment=15663105)

Chrome 实际上将连接级窗口大小增加到 15MB (15663105 65535=15MB)

Firefox

recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0> (window_size_increment=12517377)

Firefox 会将其增加到 12MB

CURL

recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0> (window_size_increment=1073676289)

curl使用 32MB

参考:https://github.com/curl/curl/blob/10cd69623a544c83bae6d90acdf141981ae53174/lib/http2.c#L62

PYTHON

recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0> (window_size_increment=16777216)

PYTHON 会将其增加到 16MB

所以我们也可以使用该参数用于指纹识别!

HEADERS

这个有点意思了

从广义上讲,HEADERS 包含了 HTTP/1.1 的所有功能,包含了 URI、方法(GET/POST/等)和客户端的头等!

下面的几个伪标头的顺序对于每个客户端是不同的。

我们来测试一下

Chrome

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(12)

image

顺序是:m,a,s,p

Firefox

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(13)

image

顺序是:m,p,a,s

CURL

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(14)

image

顺序是:m,p,s,a

Python

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(15)

image

顺序是:m,a,s,p

这个看似很小的差异,也可以用于指纹识别

HTTP/2 指纹识别在哪里使用?

它用于与TLS 指纹识别类似的目的:比如反 DDOS 和反脚本等自动爬虫(提高门槛),只允许真实浏览器等。

如何让你的server具有提取客户端HTTP2指纹的能力

ja3是tls指纹的标准,wiresharp也默认带有

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(16)

image

搞http2指纹的目前市面上还没有标准, 我开源了一款提取tls&http2指纹的中间件(面向aspnetcore的)

https://github.com/yuzd/ja3-csharp

指纹识别技术的概述(一种相对不为人知的网络指纹识别方法)(17)

image

在线测试(保护了tls指纹和用于h2指纹的关键参数):

https://kawayiyi.com/tls

{ "tlsVersion": "Tls12", "tcpConnectionId": "0HMKCUARI97OU", "tlsHashOrigin": "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-21,29-23-24,0", "tlsHashMd5": "cd08e31494f9531f560d64c695473da9", "cipherList": [ "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA" ], "extentions": [ "server_name", "extended_master_secret", "renegotiation_info", "supported_groups", "ec_point_formats", "session_ticket", "application_layer_protocol_negotiation", "status_request", "signature_algorithms", "signed_certificate_timestamp", "key_share", "psk_key_exchange_modes", "supported_versions", "compress_certificate", "extensionApplicationSettings", "padding" ], "supportedgroups": [ "X25519", "CurveP256", "CurveP384" ], "ecPointFormats": [ "uncompressed" ], "proto": "HTTP/2", "h2": { "SETTINGS": { "1": "65536", "3": "1000", "4": "6291456", "6": "262144" }, "WINDOW_UPDATE": "15663105" } }

如何过http2指纹呢?

知道了原理,还不好过吗

总结

指纹识别在整个网络中变得非常普遍,Http2的指纹相对来说不为人知,但是并不新鲜

比如这篇论文:

https://www.blackhat.com/docs/eu-17/materials/eu-17-Shuster-Passive-Fingerprinting-Of-HTTP2-Clients-wp.pdf

详细介绍了一项具有类似结论的研究

作者:俞正东

来源:halouha

出处:https://mp.weixin.qq.com/s/JgrrrCmX5Pz04pegGRrhFw

,