iOS之如何防止Charles捉包(下)

1,103 阅读3分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

前言

上一篇文章iOS之Charles抓包原理(上),我们大概描写了Charles是如何实现中间人攻击的。那这一篇,我们就来聊聊如何防止Charles捉包。

数字证书原理

  1. CA机构拥有非对称加密的私钥和公钥。
  2. CA机构对证书明文数据T进行hash
  3. hash后的值用私钥加密,得到数字签名。
  4. 明文和数字签名共同组成了数字证书

数字证书使用流程

  1. 服务端向浏览器发送数字证书(里面包含公钥,域名,明文数据等信息)
  2. CA证书的公钥对数字签名进行解密,得到一个值,可以认为是S‘
  3. 获取到明文数据T,进行hashhash后的值为h’
  4. 这时候S‘h’的内容是一样的,才代表证书是可信的,没有被篡改的。

想一下,如果明文数据T被修改了,那hash后的值,和数字签名解密后的值就不一样了,就代表证书是不可信的,数据被篡改了。

要是CA颁发的证书,那我们就通过AFNetworking请求就好,但是大多数用的都不是正规的证书,那我们要如何做呢?

解决思路

方案一:connectionProxyDictionary

我们使用NSURLSession来发起网络请求,里面有一个NSURLSessionConfiguration的配置,这个配置有一个属性叫 connectionProxyDictionary

官方给的注释是: 一般这个属性用来配置一些 需要走特定代理的连接,配置上特定的ip端口之类的,但是如果在初始化 NSURLSession 的时候将 connectionProxyDictionary 设置为,当手机开启了代理服务,用这个session 发起的网络请求并不会去走这个代理,而且默认的不走代理直接发起网络请求。

所以我们可以定义一个宏,需要再放开,来判断是否可以代理调试。这就可以做到在线上不能捉包,内部打的包可以捉包。

configuration.connectionProxyDictionary = @{};

方案二:AFN + SSL Pinning

AFN有封装类似校验证书的功能,即SSL证书绑定。通过SSL证书绑定来验证服务器身份。

  1. 首先我们APP导入cer证书,这个数字证书是可以问服务端获取的。

  2. 然后我们设置SSL Pinning 安全策略,校验模式可以设置为PublicKey,或者Certificate,具体选择可看下面的AFSecurityPolicy

  3. 利用cer证书,就能来有效地验证服务端的证书。配置好后,再设置代理,伪装的证书就无法通过验证了,就无法捉包了。

代码如下:

AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];

AFSecurityPolicy

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    // 证书是信任机构签发的就会通过
    AFSSLPinningModeNone,    
    
    // 验证服务端证书的公钥是否一致,一致就验证通过
    AFSSLPinningModePublicKey,
    
    // 验证全部信息,如证书的公钥,域名,有效期等信息,全部一致就验证通过
    AFSSLPinningModeCertificate,    
};
  • allowInvalidCertificates:允许非权威机构颁发的证书,一般设置为YES

  • validatesDomainName: 验证域名是否一致

后记

上诉2种解决方案都可以使用,从而实现防止Charles捉包。如果有不同看法,欢迎留言。

参考链接:

彻底搞懂HTTPS的加密原理