wechatpay-php icon indicating copy to clipboard operation
wechatpay-php copied to clipboard

不恰当的使用Rsa::decrypt函数(使用OPENSSL_PKCS1_PADDING填充方案),可能引起应用层存在被攻击的风险

Open TheNorthMemory opened this issue 1 month ago • 1 comments

运行环境

- OS:MacOS
- PHP: 8.3.7
- wechatpay-php: 1.4.9

描述你的问题现象

这可能不应该是件公开讨论的事宜,有关应用安全的问题可能需要具有专业知识的人来共同探讨,然而此问题在开源社区有了许多公开讨论,暂且先把问题及可能的解决方案记录于此。

缘由

在例行性更新本地PHP版本的时候,按操作习惯,会run一遍测试用例,然而有许久如下测试用例有一条F一直悬而未决:

https://github.com/wechatpay-apiv3/wechatpay-php/blob/2cabc8a15136050c4ee61083cd24959114756a03/tests/Crypto/RsaTest.php#L307-L321

现状

翻阅了PHP的更新历史及OpenSSL的更新历史,发现如下两条重要更新:

PHP自8.1.0起,使用了OpenSSL的EVP_PKEY API,且OpenSSL自3.2.0起,已显式调整EVP_PKEY_decrypt处理逻辑,默认当填充方式为RSA_PKCS1_PADDING解密失败时,不再抛异常,代为输出为随机字符串。这即是 "encrypted as OPENSSL_PKCS1_OAEP_PADDING, and decrpted as OPENSSL_PKCS1_PADDING" 用例测试未通过的原因所在。

公开的CVE/patch/backport如:

都提到了一点是,RSAES-PKCS1-v1_5已不再安全并且容易受到攻击。

受影响

目前已知在微信支付海外版,有如下两个接口声明的非对称加密方案为RSAES-PKCS1-v1_5:

身份信息校验API

• 使用微信支付平台证书的公钥,对于需要加密的参数值进行 RSA 加密。填充方案使用 RSAES-PKCS1-v1_5

Onboard Sub-merchant API

1、Perform the RSA encryption for the parameter values with the public key of the WeChat Pay Platform certificate. Use RSAES-PKCS1-v1_5 as the filling scheme.

解决方案

服务端

建议微信支付团队,评估影响等级及寻求解决方案。

客户端

本SDK(wechatpay-php)自1.2.1起,提供了OPENSSL_PKCS1_PADDING加解密支持,目前客户端暂时未发现使用OPENSSL_PKCS1_PADDING解密的场景,出于兼容性及安全考虑,需要:

  1. 调整 \WeChatPay\Crypto\Rsa::decrpt 函数,当使用OPENSSL_PKCS1_PADDING填充方案时,给予废弃及安全提示,不再推荐使用;
  2. 尝试兼容PHP低版本的ext-openssl(OpenSSL<3.2.0)解密失败抛异常行为,与OpenSSL>3.2.0默认行为保持一致,代为输出为随机字符串;
  3. 基于以上两点,修正 WeChatPay\Tests\Crypto\RsaTest::testCrossEncryptDecryptWithDifferentPadding用例覆盖;

TheNorthMemory avatar May 10 '24 08:05 TheNorthMemory