栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【网络安全】SSL Pinning及其绕过

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【网络安全】SSL Pinning及其绕过

SSL Pinning 1 HTTPS协议流程

参考:
https://segmentfault.com/a/1190000009002353?sort=newest
https://zhuanlan.zhihu.com/p/353571366

HTTPS=HTTP+TLS,其它的协议也类似,如FTPS=FTP+TLS

1) ClientHello

  • Client 首先发送本地的 TLS 版本、支持的加密算法套件,并且生成一个随机数 R1 。

2)Server Hello

  • Server 端确认 TLS 版本号。从 Client 端支持的加密套件中选取一个,并生成一个随机数 R2 一起发送给 Client。
  • Server 向 Client 发送自己的CA证书(包含公钥、证书签名)。

3)证书校验

  • Client 判断证书签名与CA证书是否合法有效
  • Client 生成随机数pre-master secret,并使用Server发过来的公钥对pre-master secret进行加密,将加密后的pre-master secret送给Server。这一步结束后,Client 与 Server 就都有 R1、R2、pre-master secret 了,两端便可以使用这 3 个随机数独立生成 对称会话密钥了,避免了对称密钥的传输,同时可以根据会话密钥生成 6 个密钥(P1~P6)用作后续身份验证

Client端和Server端,最终都会用相同的算法将pre-master secret(预主密钥)转换成master secret(主密钥),通过主密钥可以生成session key。两者后续的通信交互数据,将通过session key进行加密。

参考:https://www.laoqingcai.com/tls1.2-premasterkey/

4)Client 握手结束通知

  • Client 使用 P1 将之前的握手信息的 hash 值加密并发送给 Server
  • Client 发送握手结束消息

5)Server 握手结束通知

  • Server 计算之前的握手信息的 hash 值,并与 P1 解密客户端发送的握手信息的 hash 对比校验
  • 验证通过后,使用 P2 将之前的握手信息的 hash 值加密并发送给 Client

6)Client 开始HTTPS通讯

  • Client 计算之前的握手信息的 hash 值,并与 P2 解密 Server 发送的握手信息的 hash 对比校验
  • 验证通过后,开始发起 HTTPS 请求。

两者后续的通信交互数据,将通过session key进行加密。所以中间人即使截获数据,也无法解析。

2 证书相关 证书文件

证书=服务器公钥+(服务器公钥+服务器信息)的签名

CA

签名=摘要+私钥加密
CA:Certificate Authority,专门用自己的私钥 给别人进行签名的机构

证书的验证过程

关键过程:用信任CA库里CA证书(公钥),验证网站的证书文件里的签名

  1. 在TLS握手的过程中,客户端得到了网站的证书
  2. 客户端打开证书,查看是哪个CA签名的这个证书
  3. 在自己信任的CA库中,找相应CA的证书(包含CA的公钥),
  4. 用CA证书里面的公钥解密网站证书上的签名,取出网站证书的摘要,然后用同样的算法(比如sha256)算出网站证书的摘要,如果摘要和签名中的摘要对的上,说明这个证书是合法的,且没被人篡改过
  5. 读出里面的CN,对于网站的证书,里面一般包含的是域名
  6. 检查里面的域名和自己访问网站的域名对不对的上,对的上,就说明这个证书确实是颁发给这个网站的
  7. 到此为止检查通过
3 SSL Pinning

参考:
https://shunix.com/ssl-pinning/
https://zhuanlan.zhihu.com/p/58204817

SSL Pinning可以分为Certificate Pinning(证书锁定)和Public Key Pinning(公钥锁定)

3.1 证书锁定

把证书文件打包进安装包,将app设置为仅接受指定的内置证书,而不接受操作系统内置的CA根证书对应的任何证书。

3.2 公钥锁定

提取证书中的公钥并内置到App中,通过与服务器对比公钥值,来验证连接的合法性。我们在申请证书时,公钥在证书的续期前后可以保持不变,所以可以解决证书有效期问题。

3.3 证书锁定实例:基于TrustManagerFactory
// kotlin语法

// 加载证书文件
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
val caInput: InputStream = BufferedInputStream(FileInputStream("load-der.crt"))

// 使用CertificateFactory生成一个X509Certificate的实例
val ca: X509Certificate = caInput.use {
    cf.generateCertificate(it) as X509Certificate
}
System.out.println("ca=" + ca.subjectDN)


// 创建一个KeyStore实例,并把前边的X509Certificate实例加进去,并起一个别名"ca"
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType).apply {
    load(null, null)
    setCertificateEntry("ca", ca)
}

// 创建一个TrustManagerFactory实例,并且使用前边的KeyStore实例进行初始化
val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
    init(keyStore)
}

// 创建一个SSLContext实例,并且使用前面的TrustManagerFactory实例的trustManagers进行初始化
val context: SSLContext = SSLContext.getInstance("TLS").apply {
    init(null, tmf.trustManagers, null)
}

// 创建HttpsURLConnection实例urlConnection
val url = URL("https://certs.cac.washington.edu/CAtest/")
val urlConnection = url.openConnection() as HttpsURLConnection

// 将SSLContext实例context的socketFactory属性,赋值给urlConnection
urlConnection.sslSocketFactory = context.socketFactory

val inputStream: InputStream = urlConnection.inputStream
copyInputStreamToOutputStream(inputStream, System.out)
3.4 证书锁定实例:基于配置文件

需要在Manifest文件的android:networkSecurityConfig属性加上对应的配置内容,示例如下:



	
    
        example.com
        
            
        
    
    
    
    
        example.com
        
            7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=
            
            fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=
        
    

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1036149.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号