概述

App与服务器之间通过网络传输数据,需要确保数据在传输过程中的安全,保护传输数据的机密性和完整性,防止敏感数据被窃取和篡改是很重要的。推荐使用传输层安全协议(TLS)来保护网络传输数据的安全。

当App通过HTTPS访问云侧服务器时,如果App信任了用户安装的CA证书,则用户可以通过网络代理工具(如Fiddler、Charles)对HTTPS消息进行中间人攻击(如查看、篡改请求和响应消息),可能会导致App或云侧服务器产生安全风险,因此在通过HTTPS访问云侧服务器时应该配置CA证书进行合法性校验。

配置CA证书进行合法性校验

当App通过TLS协议连接服务器时,服务器会提供证书链来证明其身份,App需要使用可信的CA(证书颁发机构)证书对服务器证书链进行合法性校验。

服务器一般会根据场景使用不同类型CA颁发的证书链:

  1. 权威CA证书,如CFCA、GlobalSign CA机构的根CA证书,其CA证书满足业界的相关管理规范和通过审计认证,该类CA证书可信度高。
  2. 企业自建的CA证书,企业内部的服务器在不对外提供服务时,一般使用该类CA证书颁发的证书链,企业内部的App直接信任该CA证书。

系统提供了2种CA证书管理的能力,另外App也可自行管理CA证书:

  1. 系统预置CA证书:系统预置了业界主流的权威CA证书。
  2. 用户安装的CA证书:用户通过系统的设置界面安装的私有CA证书,这类CA证书可信度低。
  3. App管理的CA证书:App可以在Hap内预置可信的CA证书,例如企业内部自建的CA证书。

App应该根据业务的安全要求及应用场景进行网络连接安全配置,只信任可信的CA证书。

网络连接安全配置

配置信任系统预置的CA证书

面向互联网用户提供服务的App一般只需要信任系统预置CA证书。Network KitRemoteCommunication Kit的Https连接已默认信任系统预置的CA证书。

说明:系统Network Kit和Remote Communication Kit的Https连接默认信任系统预置的CA证书和用户安装的CA证书,可通过配置SSL Pinning证书锁定提升安全。

如果App使用三方库进行网络连接,则需要手工设置系统预置的CA证书路径:/etc/security/certificates。

示例

使用三方库curl进行HTTPS连接,通过下面代码设置信任的CA证书路径:

curl_easy_setopt( curl, CURLOPT_CATH, "/etc/security/certificates");

配置信任App管理的CA证书

如果App服务器使用企业内部自建的CA证书,则App需要配置信任自建的CA证书,App可以把自建的CA证书内置到Hap包内。

  • Network Kit和Remote Communication Kit可以使用src/main/resources/base/profile/network_config.json文件进行配置:把应用级信任的CA证书放到/res/appCaCert目录下,把特定域名信任的CA证书放到/res/domainCaCert目录下
{

  "network-security-config": {

    "base-config": {

      "trust-anchors": [

        {

          "certificates": "/res/appCaCert"

        }

      ]

    },

    "domain-config": [

      {

        "domains": [

          {

            "include-subdomains": true,

            "name": "example.com"

          }

        ],

        "trust-anchors": [

          {

            "certificates": "/res/domainCaCert"

          }

        ]

      }

    ]

  }

}

Network Kit也支持在发起HTTPS请求的代码中指定信任的CA证书路径

httpRequest.request( "EXAMPLE_URL",  {

    method: http.RequestMethod.POST,

    header: {

      'Content-Type': 'application/json'

    },

    extraData: "data to send",

    expectDataType: http.HttpDataType.STRING,

    connectTimeout: 60000,

    caPath:'/res/domainCaCert', // 指定信任的CA证书路径

}, (err: BusinessError, data: http.HttpResponse) => {

   … …

}

Remote Communication Kit也支持在代码中指定信任的CA证书路径

const caPath: rcp.CertificateAuthority = {

   folderPath: '/res/appCaCert', // 指定信任的CA证书路径

}

const securityConfig: rcp.SecurityConfiguration = {

  remoteValidation: caPath

};

// Use the security configuration in the session creation

const sessionWithSecurityConfig = rcp.createSession({ requestConfiguration: { security: securityConfig } });

说明:HarmonyOS Next 5.0版本Network Kit和Remote Communication Kit在进行上面的配置后,Https连接仍然信任系统预置的CA证书和用户安装的CA证书,可通过配置SSL Pinning证书锁定提升安全性。

  • App使用三方库进行网络连接,则需要在代码中设置App管理的CA证书路径。例如使用三方库curl进行HTTPS连接,通过下面代码设置信任的CA证书路径:
curl_easy_setopt( curl, CURLOPT_CATH, "/res/domainCaCert");

配置信任用户安装的CA证书

用户安装的CA证书可信度较低,除以下场景外,不建议App信任用户安装的CA证书:

1. App开发和调测过程中需要进行网络抓包定位问题和测试。用户通过系统的设置界面安装的CA证书,并保存在目录:/data/certificates/user_cacerts/{userid} ,其中userid从100开始。

注意:在商用发布的App版本中不应该信任用户安装的CA证书。

2. 面向2B企业应用的场景,App需要支持通过企业的代理服务器访问App服务器。设备通过企业的MDM系统或设备的管理员用户手工安装CA证书,并保存在目录:/data/certificates/user_cacerts/0

配置SSL Pinning证书锁定

一般情况下App默认信任系统预置的CA证书,如果有预置的CA 颁发了不可信证书,则应用将面临攻击的风险,对网络安全比较高的App(如金融支付、银行类应用),可以通过配置SSL Pinning证书锁定的方式只信任指定服务器证书的公钥。

配置SSL Pinning:支持两种配置方式,二选一即可。

1. 静态SSL pinning配置,通过network_config.json文件进行配置:

{

  "network-security-config": {

    "domain-config": [

      {

        "domains": [

          {

            "include-subdomains": true,

            "name": "server.com"

          }

        ],

        "pin-set": {

          "expiration": "2024-11-08",

          "pin": [

            {

              "digest-algorithm": "sha256",

              "digest": "g8CsdcpyAKxmLoWFvMd2hC7ZDUy7L4E2NYOi1i8qEtE=" //服务器证书公钥的hash

            }

          ]

        }

      }

    ]

  }

}

具体可参考配置指导的“预置锁定证书PIN”章节。

2. 动态SSL pinning:通过在代码中动态设置。

  • Network Kit配置动态SSL Pinning:
certificatePinning: [ // 可选,支持证书锁定配置信息的动态设置,自API 12开始支持该属性

    {

      publicKeyHash: 'g8CsdcpyAKxmLoWFvMd2hC7ZDUy7L4E2NYOi1i8qEtE=', // 服务器证书公钥的hash

      hashAlgorithm: 'SHA-256'

    }, {

      publicKeyHash: 'MGFiY2UyMDk5ZjEyMzI3MWQ4MDMyY2E4ODEzMmY3EtE=', // 服务器证书备用公钥的hash

      hashAlgorithm: 'SHA-256'

    }

  ]

具体可参考配置指导的“certificatePinning”参数说明

  • Remote Communication Kit配置动态SSL Pinning:
 const keyHash: string = 'g8CsdcpyAKxmLoWFvMd2hC7ZDUy7L4E2NYOi1i8qEtE='; //服务器证书的公钥

  const session = rcp.createSession();

  const request = new rcp.Request(HTTP_SERVER);

  const pin: rcp.CertificatePinning = {

    kind: 'public-key',

    publicKeyHash: keyHash,

    hashAlgorithm: 'SHA-256'

  };

  request.configuration = {

    security: {

      certificatePinning: pin,

    }

  };

  const resp = await session.fetch(request);

具体可参考配置指导的“certificatePinning”参数说明

SSL Pinning的限制和约束:

Network kit的SSL pinning要求App云侧服务器证书的公钥不能变化,如有变化需要修改App内配置的证书公钥,否则App的网络连接会失败,因此建议SSL pinning配置始终包含至少一个备用公钥。

同时,App可以设置SSL pinning的到期时间,在该时间之后不再锁定证书。这有助于在服务器证书公钥变化时,防止还未更新的App出现连接性问题。但是设置SSL pinning的到期时间可能会使攻击者绕过证书锁定。

App开发者对安全风险(如:App在应用层做了敏感信息的加密或签名,则安全风险较低)和SSL Pinning的限制约束进行充分的评估和决策是否配置。

总结

开发者应该结合App的业务场景,在不影响业务功能的情况下,合理设置可信CA证书的范围:

  1. 面向互联网用户的App,建议只需要信任系统预置的CA证书。
  2. 只访问企业内部服务器的App,建议只信任企业内部自建的CA证书。
  3. 同时访问企业内部服务器和互联网服务的App,建议根据访问的服务器域名分别配置信任系统预置的CA证书或企业内部自建的CA证书。
  4. App开发和调测过程中需要进行网络抓包定位问题和测试,建议只在调测版本信任用户安装的CA证书。
  5. App需要支持通过企业的代理服务器访问App服务器,可信任通过企业的MDM系统或设备的管理员用户手工安装CA证书,但设备的管理员用户可以通过代理工具对App网络数据进行抓包,建议App在应用层对敏感数据进行二次加密或签名。
  6. 对网络安全比较高的App(如金融支付、银行类应用),可通过SSL Pinning方式绑定服务器证书的公钥,进一步提升安全。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐