• 服务端和客户端证书各种组合下对访问者(浏览器/中间人)的影响


    今天本来想研究下nginx下如果获取SSL指纹,但是环境没有装成功

    image

    就尝试了下如果不用nginx直接在服务端拿到SSL指纹, 没想到从造自签名证书到如何开启证书, 以及服务端证书和客户端证书各种组合校验的测试就花了我很长时间。

    所以SSL指纹就下一次在研究吧,有这方面经验的朋友欢迎加我微信交流(文末)!

    本文介绍了服务端证书和客户端证书各种组合下,对于访问者(浏览器/中间人)的影响

    1. 开启服务端SSL

    
      public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseKestrel(options =>
                {
                    options.ListenLocalhost(5002, listenOption =>
                   {
                    //设置证书
                       var httpsOptions = new HttpsConnectionAdapterOptions();
                       var serverCert = new X509Certificate2("server.pfx", "1234");
                       httpsOptions.ServerCertificate = serverCert;
                       listenOption.UseHttps(httpsOptions);
                   });
                });
                webBuilder.UseStartup<Startup>();
            });
    
    

    server.pfx是自己创建的证书,需要加到根信任中心

    image

    • 浏览器访问https没问题
    • 中间人抓包没问题
    • 客户端HttpClient访问没问题

    image

    2. 开启客户端证书验证

    public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseKestrel(options =>
            {
                options.ListenLocalhost(5002, listenOption =>
               {
                //设置证书
                   var httpsOptions = new HttpsConnectionAdapterOptions();
                   //设置需要验证客户端正常开始
                   httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
                   //设置需要验证客户端正常结束
                   
                   
                   var serverCert = new X509Certificate2("server.pfx", "1234");
                   httpsOptions.ServerCertificate = serverCert;
                   listenOption.UseHttps(httpsOptions);
               });
            });
            webBuilder.UseStartup<Startup>();
        });
    
    

    只需要加一句就搞定

    但是注意 如果开启了客户端证书验证。浏览器就无法访问了。 中间人攻击如果没有证书的话 也无法完成!

    image

    • 浏览器无法访问
    • 中间人无证书无法抓包
    • 客户端HttpClient得配置证书才能访问(下面)

    3. 客户端用HttpClient加证书可以访问成功

    
    private static async Task<string> GetApiDataAsync()
    {
        try
        {
            //注意哈 这里要和服务端用的证书一样才行
            var cert = new X509Certificate2("server.pfx", "1234");
            var handler = new HttpClientHandler();
            handler.ClientCertificates.Add(cert);
    
            var client = new HttpClient(handler);
            
            var request = new HttpRequestMessage()
            {
                RequestUri = new Uri("https://localhost:5002/WeatherForecast"),
                Method = HttpMethod.Get,
            };
    
            var response = await client.SendAsync(request);
    
            if (response.IsSuccessStatusCode)
            {
                var responseContent = await response.Content.ReadAsStringAsync();
                return responseContent;
            }
    
            throw new ApplicationException($"Status code: {response.StatusCode}, Error: {response.ReasonPhrase}");
        }
        catch (Exception e)
        {
            throw new ApplicationException($"Exception {e}");
        }
    }
        
    

    image

    4. 服务端开启客户端证书校验

    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseKestrel(options =>
            {
                options.ListenLocalhost(5002, listenOption =>
               {
                //设置证书
                   var httpsOptions = new HttpsConnectionAdapterOptions();
                   //设置需要验证客户端正常开始
                   httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
                   //设置需要验证客户端正常结束
                   
                   //设置服务端验证客户端 开启SSL Pinning start
                   httpsOptions.CheckCertificateRevocation = true;
                   httpsOptions.ClientCertificateValidation +=
                       (certificate2, chain, arg3) =>
                       {
                           //return true;
                           //this is where we verify the thumbprint of a connected client matches the thumbprint we expect
                           //NOTE: this is just a simple example of verifying a client cert.
                           // 2A39D43A8FE2CAE54542C768F61AE79097FAB6F5 这个是我那个证书的 测试的话需要换下
                           return certificate2.Thumbprint.Equals(
                              "2A39D43A8FE2CAE54542C768F61AE79097FAB6F5",
                              StringComparison.InvariantCultureIgnoreCase);
                       };               
                   
                   //设置服务端验证客户端 开启SSL Pinning end
                   var serverCert = new X509Certificate2("server.pfx", "1234");
                   httpsOptions.ServerCertificate = serverCert;
                   listenOption.UseHttps(httpsOptions);
               });
            });
            webBuilder.UseStartup<Startup>();
        });
    
    

    注意:服务端开启验证的前提是需要客户端传证书

    相比上面一步,更加保证了客户端传的证书的安全性。

    而且只要约束了客户端传证书,中间人抓https的包如果拿不到证书是无法抓的!!

    • 浏览器无法访问
    • 中间人无证书无法抓包
    • 客户端HttpClient得配置证书才能访问(同上)

    5. 客户端开启SSL Pinning

    不需要客户端传证书(不需要服务端强制开启客户端传证书)

    只在客户端验证服务端证书。

    客户端HttpClient访问增加开启 SSL Pinning

    
    var handler = new HttpClientHandler();
    var client = new HttpClient(handler);
    //增加开启 SSL Pinning
    handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
    {
        //2A39D43A8FE2CAE54542C768F61AE79097FAB6F5 这个是我那个证书的 测试的话需要换下
        return cert.Thumbprint.Equals("2A39D43A8FE2CAE54542C768F61AE79097FAB6F5",
            StringComparison.CurrentCultureIgnoreCase);
    };
    
    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri("https://localhost:5002/WeatherForecast"),
        Method = HttpMethod.Get,
    };
    
    var response = await client.SendAsync(request);
    

    image

    试下对中间人攻击有没有效果

    开启并设置Fiddler代理

    handler.Proxy = new WebProxy("127.0.0.1:8888");
    

    image

    如上图,启动中间人攻击后的服务端证书签名变了

    • 浏览器可访问
    • 中间人无证书情况无法抓包

    综上 在客户端启动SSL pinning 最简单,成本最小,其他语言都有比较简单的实现

    上面演示的证书链只有一条,验证的时候也可以对整个证书链遍历,每个都验证最为稳妥!

    不过不能以为客户端开启了SSL Pinning就安全了,因为客户端有Hook(xpose,frida).

    SSL指纹有感兴趣的可以加我交流,备注下ssl。

    image


    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,转载文章之后须在文章页面明显位置给出作者和原文连接,谢谢。
  • 相关阅读:
    【架构】如何设计支持多租户的数据库?
    maven的仓库:本地和远程
    maven私服
    MSA(微服务简介)
    json数据的格式
    shiro的原理理解
    异构的概念?大数据量的异构处理?
    面试之多线程通信
    面试之并发的解决方案
    进程与线程的简单理解
  • 原文地址:https://www.cnblogs.com/yudongdong/p/14801700.html
Copyright © 2020-2023  润新知