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

上一部分我介绍了有关TLS 指纹识别方法(以及在不同客户端的指纹有何区别):

https://mp.weixin.qq.com/s/BvotXrFXwYvGWpqHKoj3uQ

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

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

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

在chrome上看是这样的

在Firefox上看是这样的

HTTP/2 的主要目标是提高性能
  • 多路复用(Multiplexing ) - 多个请求和响应可以同时共享同一个 TCP 连接,从而减少了获取具有大量资源(图像、脚本等)的站点的时间。
  • 优先级(PRIORITY) - HTTP/2 支持对某些请求和响应进行优先级排序。
  • 服务器推送(Server push) - 在 HTTP/2 中,服务器可以在客户端请求资源之前将资源发送给客户端。

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

Frames and Streams

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

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

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

  • SETTINGS是客户端发送的第一帧,包含 HTTP/2 的特定配置,
  • WINDOW_UPDATE- 增加接收器的窗口大小,下面会讲到

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

  • HEADERS 包含 URI、HTTP 方法和客户端的 HTTP 头
  • DATA 包含来请求的资源数据以及服务器的响应

使用 HTTP/2 进行客户端指纹识别

研究http2协议的工具

这里推荐使用nghttpd,它可以很方便的创建一个http2协议的webserver。

最关键的是,让客户端请求的时候它能够直观的把每一帧都给打印出来(下面会给大家演示)

我将它安装在wsl的ubuntu机器上,还得自建一个证书,这里我遇到了一点坑,

避坑指南请看我写的(wsl创建证书让chrome浏览器识别):

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

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

  • Chrome浏览器
  • Firefox浏览器
  • CURL
  • Python脚本

1. SETTINGS

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

Chrome

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

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

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

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/等)和客户端的头等!

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

  • :method
  • :authority
  • :scheme
  • :path

我们来测试一下

Chrome

顺序是:

m,a,s,p

Firefox

顺序是:

m,p,a,s

CURL

顺序是:

m,p,s,a

Python

顺序是:

m,a,s,p

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

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

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

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

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

搞http2指纹的目前市面上还没有标准,

我开源了一款提取tls&http2指纹的中间件(面向aspnetcore的)

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

在线测试:

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

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

本文参考了@lwthiker大神的研究,加上了自己的实践(解析http2协议),感谢他的指点

HTTP2指纹识别(一种相对不为人知的网络指纹识别方法)的更多相关文章

  1. 利用神经网络进行网络流量识别——特征提取的方法是(1)直接原始报文提取前24字节,24个报文组成596像素图像CNN识别;或者直接去掉header后payload的前1024字节(2)传输报文的大小分布特征;也有加入时序结合LSTM后的CNN综合模型

    国外的文献汇总: <Network Traffic Classification via Neural Networks>使用的是全连接网络,传统机器学习特征工程的技术.top10特征如下 ...

  2. 不为人知的网络编程(八):从数据传输层深度解密HTTP

    1.引言 在文章<理论联系实际:Wireshark抓包分析TCP 3次握手.4次挥手过程>中,我们学会了用wireshark来分析TCP的“三次握手,四次挥手”,非常好用.这就是传说中的锤 ...

  3. PatentTips -- 一种在CoAP网络中注册的方法及装置

    技术领域 [0001] 本发明涉及一种在CoAP网络中注册的方法及装置,属于网络通信技术领域. 背景技术 [0002] (Internet of Things,物联网)作为新一代的信息技术,越来越受到 ...

  4. 不为人知的网络编程(九):理论联系实际,全方位深入理解DNS

    本文原作者:selfboot,博客地址:selfboot.cn,Github地址:github.com/selfboot,感谢原作者的技术分享. 1.引言 对于 DNS(Domain Name Sys ...

  5. larbin是一种开源的网络爬虫/网络蜘

    larbin是一种开源的网络爬虫/网络蜘蛛,由法国的年轻人 Sébastien Ailleret独立开发.larbin目的是能够跟踪页面的url进行扩展的抓取,最后为搜索引擎提供广泛的数据来源.Lar ...

  6. PHP几种抓取网络数据的常见方法

    //本小节的名称为 fsockopen,curl与file_get_contents,具体是探讨这三种方式进行网络数据输入输出的一些汇总.关于 fsockopen 前面已经谈了不少,下面开始转入其它. ...

  7. 微软引入了两种新的网络过滤系统,WFP和NDISfilter

    Windows 8是微软公司推出的最新的客户端OS,内部名称Windows NT 80.相对于Windows NT 5.x,其网络结构变化非常大,原有的TDI,NDIS系统挂接方法不再适用.在Wind ...

  8. opencv —— 同时识别三种颜色

    要点: 1.识别一种颜色 minH = ; //色相 maxH = ; minS = ; //饱和度 maxS = ; minV = ; // inRange(原图像, 最小值的范围, 最大值的范围, ...

  9. 【Android】一种提高Android应用进程存活率新方法

    [Android]一种提高Android应用进程存活率新方法 SkySeraph Jun. 19st 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph ...

随机推荐

  1. pyenv安装及使用教程

    pyenv安装及使用教程 pyenv 安装 git clone https://github.com/pyenv/pyenv.git ~/.pyenv # 编辑 bashrc vim ~/.bashr ...

  2. 简单实现python接口自动化(一)

    目的:excel中维护接口用例数据,通过python中requests库进行读取用例,并把运行结果与excel中的预期结果对比,最后把执行情况写入到excel中去. excel维护数据: 具体的接口名 ...

  3. 【python量化】将Transformer模型用于股票价格预测

    本篇文章主要教大家如何搭建一个基于Transformer的简单预测模型,并将其用于股票价格预测当中.原代码在文末进行获取.小熊猫的python第二世界 1.Transformer模型 Transfor ...

  4. NC204382 中序序列

    NC204382 中序序列 题目 题目描述 给定一棵有 \(n\) 个结点的二叉树的先序遍历与后序遍历序列,求其中序遍历序列. 若某节点只有一个子结点,则此处将其看作左儿子结点 示例1 输入 5,[3 ...

  5. 一文聊透 Netty 核心引擎 Reactor 的运转架构

    本系列Netty源码解析文章基于 4.1.56.Final版本 本文笔者来为大家介绍下Netty的核心引擎Reactor的运转架构,希望通过本文的介绍能够让大家对Reactor是如何驱动着整个Nett ...

  6. STM32液晶显示HT1621驱动原理及程序代码

    1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机 ...

  7. 栈(Stack)和队列

    栈(Stack)和队列 栈是一个后进先出的线性表,它要求只在表尾进行删除和插入操作. 所谓的栈,其实就是一个特殊的线性表.表尾称为栈顶(Top),相应的表头称为栈底(Bottom). 栈的插入(Pus ...

  8. Java 17 中的模式匹配与和类型

    Java 17 中的模式匹配与和类型 从 Spring Security 获取用户谈起 使用 Spring Security做用户校验和权限控制时,常常使用和线程绑定的容器来获取当前登录用户. // ...

  9. nexus org.sonatype.nexus.bootstrap.jetty.JettyServer - Start failed

    INFO [jetty-main-1] *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer - Runningjvm 1 | 2020-04- ...

  10. Python究竟属不属于嵌入式语言?

    写在前面: 几十年来,大家普遍的认为C与C++才是标准的嵌入式语言,那么现在大火的Python算是一种嵌入式语言吗? 在给出我的答案之前我们要先明确几个问题? 什么是Python? 编程语言的定义? ...