日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/4 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 web容器获取SSL指纹实现和ByPass 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

前段時間對SSL指紋的獲取實現很感興趣,從表面到深入再到實現讓我更加深刻理解SSL設計。
本篇介紹:

  • SSL指紋在web容器(Kestrel)下如何獲取,并實現一個Middleware來很方便集成到web工程里面(下文附源碼地址)。

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

  • 測試不同的客戶端的SSL指紋(java curl Fiddler python csharp chrome edge)

本次對SSL指紋的研究就算是完結篇了,
本次系列

  • 從SSL的理解誤區走出

  • SSL證書的作用表現

  • 正文開始

  • 先來說說這個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 有辦法??當然可以

    可以私信交流


    我是正東,學的越多不知道也越多。如果決定去深究一個東西, 一定要完全搞懂, 并認真總結一篇博客讓以后能在短時間拾起來 ( 因為不搞懂你很難寫一篇半年后還能理解的博客 )

    歡迎白嫖點贊!

    總結

    以上是生活随笔為你收集整理的web容器获取SSL指纹实现和ByPass的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。