web容器获取SSL指纹实现和ByPass

前言

前段时间对SSL指纹的获取实现很感兴趣,从表面到深入再到实现让我更加深刻理解SSL设计。
本篇介绍:

  • SSL指纹在web容器(Kestrel)下如何获取,并实现一个Middleware来很方便集成到web工程里面(下文附源码地址)。

  • 解析ClientHello的套路以及如何生成SSL指纹

  • 测试不同的客户端的SSL指纹(java curl Fiddler python csharp chrome edge)

本次对SSL指纹的研究就算是完结篇了,
本次系列

  1. 从SSL的理解误区走出

  2. SSL证书的作用表现

  3. 正文开始

先来说说这个SSL指纹用来干嘛

  • waf里面一般会有用到

  • 说实话在目前的话也只能干干script Boy

举个例子,之前看过说为什么同样的请求地址一样的参数 一样的httpHeader,在浏览器访问就正常,用python发送的就会被waf拦截

正常用户访问:

[截图出自ParrotSecurity的A佬]

script Boy 用Python 发 Request,直接就被waf拦截了

[截图出自ParrotSecurity的A佬]

类似这样的求问帖有很多

  • https://stackoverflow.com/questions/60407057/python-requests-being-fingerprinted

  • https://stackoverflow.com/questions/63343106/how-to-avoid-request-fingerprinted-in-python

结论就是 python的tls握手有特征,被waf识别到独特的指纹了!

SSL指纹识别原理

巨人的肩膀在这里:https://github.com/salesforce/ja3

就是解析TLS握手客户端发送的ClientHello报文并获取

  • SSLVersion 版本

  • Cipher 客户端支持的加密套件

  • SSLExtention SSL的扩展内容集合

  • EllipticCurve SSL的扩展内容里面的【supported_groups】(CurveP256,CurveP384,CurveP521,X25519)

  • EllipticCurvePointFormat SSL的扩展参数里面的【sec_point_formats】(uncompressed,ansiX962_compressed_prime,ansiX962_compressed_char2)

把上面解析出来的版本,加密套件,扩展等内容按顺序排列然后计算hash值,便可得到一个客户端的TLS FingerPrint,waf防护规则其实就是整理提取一些常见的非浏览器客户端requests,curl的指纹然后在客户端发起https请求时进行识别并拦截!

同一个客户端的报文对比,除了Ramdom和SessionId有变化其他不变

不同的客户端的报文对比就各式各样了

动手实践

本次技术实现基于aspnet5.0,web容器是微软为aspnetcore打造的高性能Kestrel!
得益于Kestrel的中间件设计,我们可以很容易的
在配置Kestrel的时候指定自己的中间件去拦截ClientHello
(感谢微软大神davidfowl的指点)

webBuilder.UseKestrel(options =>
{var logger = options.ApplicationServices.GetRequiredService<ILogger<Program>>();options.ListenLocalhost(5002, listenOption =>{var httpsOptions = new HttpsConnectionAdapterOptions();//本地测试证书var serverCert = new X509Certificate2("server.pfx", "1234");httpsOptions.ServerCertificate = serverCert;//注册tls拦截中间件listenOption.Use(async (connectionContext, next) =>{await TlsFilterConnectionMiddlewareExtensions.ProcessAsync(connectionContext, next, logger);});listenOption.UseHttps(httpsOptions);});
});

接下来就是在我们自定义的中间件做解析

public static async Task ProcessAsync(ConnectionContext connectionContext, Func<Task> next, ILogger<Program> logger)
{var input = connectionContext.Transport.Input;var minBytesExamined = 0L;while (true){var result = await input.ReadAsync();var buffer = result.Buffer;if (result.IsCompleted){return;}if (buffer.Length == 0){continue;}//开启处理ClientHello报文if (!TryReadHello(buffer, logger, out var abort)){minBytesExamined = buffer.Length;input.AdvanceTo(buffer.Start, buffer.End);continue;}//上面我们读了流这里要归位var examined = buffer.Slice(buffer.Start, minBytesExamined).End;input.AdvanceTo(buffer.Start, examined);if (abort){// Close the connection.return;}break;}await next();
}

解析ClientHello报文

private static bool TryReadHello(ReadOnlySequence<byte> buffer, ILogger logger, out bool abort)
{abort = false;if (!buffer.IsSingleSegment){throw new NotImplementedException("Multiple buffer segments");}var data = buffer.First.Span;TlsFrameHelper.TlsFrameInfo info = default;if (!TlsFrameHelper.TryGetFrameInfo(data, ref info)){return false;}//解析的版本logger.LogInformation("Protocol versions: {versions}",      info.SupportedVersions);//解析客户端请求的Host//这里有一个小技巧,waf防御的一个简单的ByPass手段就是绕过域名直接访问Ip进行访问,如果服务端在这里增加一个Host白名单,就能防止绕过。logger.LogInformation("SNI: {host}", info.TargetName);//其他字段省略Console.WriteLine("ClientHello=>" + info);return true;
}

ClientHello报文解析

解析报文没啥特别的,就是根据RCF文档,:

 public enum ExtensionType : ushort{server_name = 0,max_fragment_length = 1,client_certificate_url = 2,trusted_ca_keys = 3,truncated_hmac = 4,status_request = 5,user_mapping = 6,client_authz = 7,server_authz = 8,cert_type = 9,supported_groups = 10,//  Elliptic curve pointsec_point_formats = 11, // Elliptic curve point formatssrp = 12,signature_algorithms = 13,use_srtp = 14,heartbeat = 15,application_layer_protocol_negotiation = 16,status_request_v2 = 17,signed_certificate_timestamp = 18,client_certificate_type = 19,server_certificate_type = 20,padding = 21,encrypt_then_mac = 22,extended_master_secret = 23,token_binding = 24,cached_info = 25,tls_lts = 26,compress_certificate = 27,record_size_limit = 28,pwd_protect = 29,pwd_clear = 30,password_salt = 31,session_ticket = 35,pre_shared_key = 41,early_data = 42,supported_versions = 43,cookie = 44,psk_key_exchange_modes = 45,certificate_authorities = 47,oid_filters = 48,post_handshake_auth = 49,signature_algorithms_cert = 50,key_share = 51,renegotiation_info = 65281}

tips:解析Extention的套路:

byte数组 前2个byte为长度 后面的是内容 然后根据RFC的struct进行解析

struct枚举 我从Go SDK的tls直接复制过来用的

GoSDK里面的注释很详细 RFC的相关也在注释里面,点赞!

这部分代码有点多,我都放在了我的github,想研究的可以
点击查看

最后就是按照原理将数据进行拼接在md5生成SSL指纹
public string getSig()
{StringBuilder sb = new StringBuilder();//版本sb.Append((int)Header.Version);sb.Append(",");//加密套件if (_ciphers != null){sb.Append(string.Join("-", _ciphers.Select(r => (int)r)));}sb.Append(",");//SSL扩展字段if (_extensions != null){sb.Append(string.Join("-", _extensions.Select(r => (int)r)));}sb.Append(",");//Elliptic curve pointsif (_supportedgroups != null){sb.Append(string.Join("-", _supportedgroups.Select(r => (int)r)));}sb.Append(",");// Elliptic curve point formatsif (_ecPointFormats != null){sb.Append(string.Join("-", _ecPointFormats.Select(r => (int)r)));}String str = sb.ToString();using var md5 = MD5.Create();var result = md5.ComputeHash(Encoding.ASCII.GetBytes(str));var strResult = BitConverter.ToString(result);//和其他语言的实现保持一致var sig = strResult.Replace("-", "").ToLower();return sig;
}

精彩时刻 来试试效果

用不同的客户端来测试下看看收集的指纹

1. chrome
指纹:
192,
0-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-21,
29-23-24,
0
2. edge
指纹:
192,
0-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

新版edge也是用的chromium的内核,Extention扩展多了一个17513

3. csharp的HttpClient
指纹:
3072,
49196-49195-49200-49199-159-158-49188-49187-49192-49191-49162-49161-49172-49171-157-156-61-60-53-47-10,
0-10-11-13-35-23-65281,
29-23-24,
0
4. Fiddler
指纹:
3072,
49196-49195-49200-49199-159-158-49188-49187-49192-49191-49162-49161-49172-49171-157-156-61-60-53-47-10,
0-10-11-13-35-23-65281,
29-23-24,
0

因为Fiddler是csharp写的,应该用的都是微软的封装的ssl实现吧。
所以和csharp的HttpClient是一样的指纹。

5. java JDK自带的HttpsURLConnection
指纹:
3072,
49187-49191-60-49189-49193-103-64-49161-49171-47-49156-49166-51-50-49195-49199-156-49197-49201-158-162-49160-49170-10-49155-49165-22-19-255,
10-11-13,
23-1-3-19-21-6-7-9-10-24-11-12-25-13-14-15-16-17-2-18-4-5-20-8-22,
0

明显可以看出来 EllipticCurve 多了很多!

6. Apache HttpClient
指纹:
3072,
49188-49192-61-49190-49194-107-106-49162-49172-53-49157-49167-57-56-49187-49191-60-49189-49193-103-64-49161-49171-47-49156-49166-51-50-49196-49195-49200-157-49198-49202-159-163-49199-156-49197-49201-158-162-255,
10-11-13-23,
23-24-25,
0

相比上面几个 在 EllipticCurve 上面有明显不一样!

7. curl
指纹:
192,
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-13172-16-22-23-49-13-43-45-51-21,
29-23-30-25-24,
0-1-2
8. python3的Request
指纹:
192,
4866-4867-4865-49196-49200-49195-49199-52393-52392-163-159-162-158-52394-49327-49325-49188-49192-49162-49172-49315-49311-107-106-57-56-49326-49324-49187-49191-49161-49171-49314-49310-103-64-51-50-157-156-49313-49309-49312-49308-61-60-53-47-255,
0-11-10-35-22-23-13-43-45-51-21,
29-23-30-25-24,
0-1-2

哈哈,实践是检验真理的唯一标准,
不难看出来为什么阿里的waf这么容易就能干掉curl 和 python脚本

ByPass 有办法??当然可以

可以私信交流


我是正东,学的越多不知道也越多。如果决定去深究一个东西, 一定要完全搞懂, 并认真总结一篇博客让以后能在短时间拾起来 ( 因为不搞懂你很难写一篇半年后还能理解的博客 )

欢迎白嫖点赞!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

许可证( License LicenseLicenseLicenseLicenseLicense)服务器配置

在这里我要说明一下&#xff0c;如果你没有lic文件&#xff0c;可以到官方注册帐号&#xff0c;进行申请&#xff0c;我这里我申请的是一个90天的试用的序列号&#xff0c;下面是我在配置过程中的一些截图发出来。大家可以看一下。 老样子&#xff0c;开机过几秒中会提示出来的…

java struts 文件下载_Struts2文件下载实例

通过《Struts2文件下载简介》教程的学习&#xff0c;读者已经了解了使用 Struts2 框架实现在指定的目录中下载指定文件的功能。下面通过案例演示文件下载功能。1)创建下载页面在 struts2Demo06 项目的 WebContent 目录下创建一个名称为 download.jsp 的页面文件&#xff0c;在文…

预售┃16个有趣的海洋实验,美到让人窒息!

▲数据汪特别推荐点击上图进入玩酷屋我们的孩子&#xff0c;在科技发展迅速的年代&#xff0c;从出生就接触着各种高科技&#xff0c;接触电子产品已经是必然。但小木时常在想&#xff0c;除了ipad和那些普通的玩具&#xff0c;我们还能给孩子玩儿些什么呢&#xff1f;有没有宝…

深入LINQ | 揭开IQueryable的面纱

原文&#xff1a;bit.ly/3uAXliC作者&#xff1a;Jeremy Likness译者&#xff1a;精致码农-王亮在上一篇深入LINQ | 动态构建LINQ表达式 博文中&#xff0c;我们探索了表达式的强大&#xff0c;并用它来动态地构建一个基于 JSON 的规则引擎。在这篇文章中&#xff0c;我们反过来…

科幻作家阿西莫夫上世纪预言2019: 计算机彻底变革教育,太空移民进行中

全世界只有3.14 % 的人关注了数据与算法之美2019年必将是充满机遇与挑战的一年&#xff0c;一年的时间世界可能发生很大的变化。我们应该如何期待新的一年&#xff1f;在这&#xff0c;数据汪带大家重新读1983年美国作家艾萨克阿西莫夫&#xff08;Isaac Asimov&#xff09;对2…

6月程序员平均工资出炉,你拖后腿了吗?

据有关部门统计&#xff1a;6月份全国招收程序员435501人&#xff0c;平均工资为15052元&#xff0c;很多小伙伴儿纷纷感慨工资被平均了。然而6月程序员工资的中位数却是13000元&#xff0c;这说明什么&#xff1f;也许不是被平均&#xff0c;而是真的拖后腿了&#xff0c;下面…

学习爬虫限时只需9.9,还在犹豫什么?

收拾行李回老家的小天&#xff0c;新春福利还是要准时送到大家手上的&#xff01;随着互联网的发展&#xff0c;google、百度等搜索引擎让我们获取信息愈加方便。Python是当今世界最热门的编程语言之一&#xff0c;在科研领域也发挥着强大的作用&#xff0c;尤其是在日常的学习…

如何快速正确的安装 Ruby, Rails 运行环境

2019独角兽企业重金招聘Python工程师标准>>> 系统需求 首先确定操作系统环境&#xff0c;不建议在 Windows 上面搞&#xff0c;所以你需要用: Mac OS X任意 Linux 发行版本(Ubuntu,CentOS, Redhat, ArchLinux ...)强烈新手使用 Ubuntu 省掉不必要的麻烦&#xff01;…

你怕是对MD5算法有误解

大家常听到“MD5加密”、“对称加密”、“非对称加密”&#xff0c;那么MD5属于哪种加密算法&#xff1f;面试官问这样的问题&#xff0c;准是在给你挖坑。"MD5加密"纯属口嗨&#xff0c;MD5不是加密算法&#xff0c;是摘要算法。今天小码甲带大家梳理加密算法、摘要…

还在集什么五福,史上最惨锦鲤再次来袭!奖品堪比5年高考3年模拟!

全世界只有3.14 % 的人关注了数据与算法之美在锦鲤盛行的2018年我们超级数学建模也跟风来了一个“史上最惨锦鲤”活动为什么叫史上最惨锦鲤呢因为平常看一本数学书就已经头疼了何况我们奖品还是100本数学书试问除了学霸还有谁能承受这种殊荣巧的是最后的得主还真是一个学霸那就…

Python: logging日志模块简单示例

2019独角兽企业重金招聘Python工程师标准>>> Python的logging模块提供了通用的日志系统&#xff0c;可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别&#xff0c;并可以采用不同的方式记录日志&#xff0c;比如文件&#xff0c;HTTP GET/POST&#x…

开源基金会为何辟谣 鸿蒙背后有何玄机

最近&#xff0c;鸿蒙OS曝光率极高&#xff0c;受网络舆论热捧。铁流原本是不太愿意碰这个雷的&#xff0c;因网友提问&#xff0c;所以谈一谈这个事情。OpenHarmony和Harmony是两回事6月2日&#xff0c;公司官宣鸿蒙OS&#xff0c;给出了百台机型的升级计划&#xff0c;而且还…

java get image获取根路径_Java 获取资源文件路径

1 问题描述通过源码运行时&#xff0c;一般使用如下方式读取资源文件&#xff1a;String str "1.jpg";资源文件与源码文件放在同一目录下&#xff0c;或者拥有同一父级目录&#xff1a;String str "a/b/1.jpg";这样直接编译运行没有问题&#xff0c;但是…

阿里云开源的Blink,计算能力很疯狂:一眨眼,全部都算好!

全世界只有3.14 % 的人关注了数据与算法之美前两天&#xff0c;阿里云宣布开源“计算王牌”——实时计算平台Blink&#xff0c;回馈给ApacheFlink社区。官方称&#xff0c;计算延迟已经降到毫秒级&#xff1a;浏览网页的时候&#xff0c;你只是眨了一下眼睛&#xff0c;但在淘宝…

NET问答: 如何用 C# 计算相对时间 ?

咨询区 Jeff Atwood&#xff1a;给定一个 DataTime 值&#xff0c;如何计算如下时间&#xff1f;比如说&#xff1a;2 小时前&#xff1f;3 天前&#xff1f;1 个月前&#xff1f;回答区 neuracnu&#xff1a;我在 DateTime 类上做了一个扩展方法&#xff0c;你可以给它传递未来…

有趣程序和让人捧腹大笑的注释,你的注释还不够骚

全世界只有3.14 % 的人关注了数据与算法之美一&#xff0c;这个是关于数组的操作&#xff0c;数据汪也是才知道&#xff0c;居然还有这种操作# include <stdio.h>int main(){ int num[] {1,2,3,4};printf("the 3[num] result is : %d\n", 2[num]);return 0;}结…

.NET之盛派微信SDK简单操作

开篇语在6月5号&#xff0c;我报名去参加了微软举办的一个线下分享的技术市集&#xff0c;分享人是苏老师和赵老师(非常感谢)&#xff0c;其中苏老师讲述了关于一些容器的部署等操作(也可以观看我的历史文章)&#xff0c;其中关于部署的示例代码是使用盛派微信SDK做了一个对接微…

预售┃连锁反应装置积木好玩到尖叫!

▲数据汪特别推荐点击上图进入玩酷屋之前推荐的“小小机械师”成了孩子最受欢迎的玩具&#xff0c;玩了的孩子几乎没有不喜欢的。还有家长买多套送给朋友的孩子作为生日礼物。有家长来问&#xff0c;还有没有这种类型的新产品。和厂家咨询后&#xff0c;小木找到了一款“小小机…

VMware VSphere 虚拟化云计算学习配置笔记(四)

2:接下来配置安装vcenter-db&#xff0c;安装MS SQL 2008r2 在vcenter-db服务器上安装配置MS SQL 2008r2过程截图&#xff1a; 这里可能会要耐心等一下才会出现一下提示&#xff1a; 选择左边installation 之后出现右边第一项新的安装&#xff1a; 转载于:https://blog.51cto.c…

IT人回家过年的尴尬

全世界只有3.14 % 的人关注了数据与算法之美春节将至&#xff0c;有很多人已经踏上了返乡的旅途&#xff0c;回家开开心心过春节&#xff0c;归心似箭的心表明了他们对家乡的热爱&#xff0c;归心似箭的心显示了他们想念父母的情&#xff0c;归心似箭的心代表了他们对朋友的思。…