Technical Details of CVE-2020-23533, CVE-2020-36284, CVE-2020-36285 Related to Improper Signature Verification in UnionPay SDK

Supporting materials for CUHK's research of [R2]

In this webpage, we provide the supplementary materials for the 3 CVEs in UnionPay SDK, following our research on the Security Analysis of Mobile Payment Platforms (Cashiers).
The findings were reported by Shangcheng Shi from CUHK MobiTeC to the MITRE CVE Database, and detailed in the research paper below.

Research Paper

[R2] Shangcheng Shi, Xianbo Wang, and Wing Cheong Lau. 2021. Breaking and Fixing Third-Party Payment Service for Mobile Apps. In Applied Cryptography and Network Security: 19th International Conference, ACNS 2021, Kamakura, Japan, June 21–24, 2021, Proceedings, Part II. Springer-Verlag, Berlin, Heidelberg, 3–26.
DOI: https://doi.org/10.1007/978-3-030-78375-4_1

CVE Email Correspondence

Original Report by CUHK MobiTeC to MITRE CVE Database:

Confirmation from MITRE on the assignment of CVEs:

Background

UnionPay is now accepted by over 28 million merchants across the globe. Many of the merchants integrate UnionPay's online payment service for their websites and mobile apps. As security researchers, we have found a serious vulnerability within UnionPay's backend SDK to the merchants which enables an attacker to shop for free in merchants' websites and mobile apps (in both Android and iOS).

Description

When using UnionPay's online payment service, for either websites or mobile apps, each merchant needs to provide a notification URL (hosted by the merchant server) to accept the payment results that are digitally signed by UnionPay's cashier server. UnionPay provides SDKs to be incorporated in merchant servers to handle and verify these payment results. Unfortunately, UnionPay inadvertently includes a vulnerability in the PHP version of its SDK, enabling the attacker to bypass the signature verification of the payment messages. Consequently, an attacker can build malicious payloads and send them to the notification URL hosted by the merchant server to shop for free.

CVE Details

For web-based services: the affected SDK version up is up to 1.2.0, which has been assigned CVE-2020-23533.

  • Description: Union Pay up to 1.2.0, for web based versions contains a CWE-347: Improper Verification of Cryptographic Signature vulnerability, allows attackers to shop for free in merchants' websites and mobile apps, via a crafted authentication code (MAC) which is generated based on a secret key which is NULL.
  • Online Archive for vulnerable PHP SDK: Dropbox Link

For Android payment services: the affected SDK version up is up to 3.4.93.4.9, which has been assigned CVE-2020-36284.

  • Description: Union Pay up to 3.4.93.4.9, for android, contains a CWE-347: Improper Verification of Cryptographic Signature vulnerability, allows attackers to shop for free in merchants' websites and mobile apps, via a crafted authentication code (MAC) which is generated based on a secret key which is NULL.
  • Online Archive for vulnerable PHP SDK: Dropbox Link

For iOS payment services: the affected SDK version up is up to 3.3.12, which has been assigned CVE-2020-36285.

  • Description: Union Pay up to 3.3.12, for iOS mobile apps, contains a CWE-347: Improper Verification of Cryptographic Signature vulnerability, allows attackers to shop for free in merchants' websites and mobile apps, via a crafted authentication code (MAC) which is generated based on a secret key which is NULL.
  • Online Archive for vulnerable PHP SDK: Dropbox Link

Remark: We have made the responsible disclosure to UnionPay, while the vendor immediately updated its SDKs after our report. As a result, these vulnerable SDKs mentioned above are no longer hosted on the webpage of UnionPay.

Since these SDKs are almost the same, we use the one for web-based services as illustration. The following snippets are from the SDK and used to verify the payment results (from the UnionPay's cashier server).

sdk/acp_service.php:

line 156                static function validate($params) {
line 157
line 158                        $logger = LogUtil::getLogger();
line 159
line 160                        $isSuccess = false;
line 161
line 162                        if($params['signMethod']=='01')
line 163                        {
line 164                                $signature_str = $params ['signature'];
line 165                                unset ( $params ['signature'] );

...

line 198                        } else {
line 199                                $isSuccess = AcpService::validateBySecureKey($params, SDKConfig::getSDKConfig()->secureKey);
line 200                        } 
line 201                        return $isSuccess;
line 202                }

...

line 204                static function validateBySecureKey($params, $secureKey) { 
line 205
line 206                        $logger = LogUtil::getLogger();
line 207                        $isSuccess = false;
line 208
line 209                        $signature_str = $params ['signature'];
line 210                        unset ( $params ['signature'] );
line 211                        $params_str = createLinkString ( $params, true, false );

...

line 215                        if($params['signMethod']=='11') {
line 216
line 217                                $params_before_sha256 = hash('sha256', $secureKey);
line 218                                $params_before_sha256 = $params_str.'&'.$params_before_sha256;
line 219                                $params_after_sha256 = hash('sha256',$params_before_sha256);
line 220                                $isSuccess = $params_after_sha256 == $signature_str;

...

line 231                        return $isSuccess;

sdk/SDKConfig.php:

line 111        $this->secureKey =  array_key_exists("acpsdk.secureKey", $sdk_array)?$sdk_array["acpsdk.secureKey"]: null;

Illustration

UnionPay provides two options to protect the payment results from its cashier server, namely digital signature and message authentication code (MAC). Notably, the digital signature is the de facto standard for protecting the payment results, while the MAC is only used by old merchant servers and not adopted by new ones.

As we see from the code (line 162 in acp_service.php), validate() dynamically extracts the 'signMethod' field to determine whether digital signature (i.e., '01') or MAC (e.g., '11') is used. Such practice enables the attacker to send a message protected by MAC to the merchant server using the digital signature by controlling the 'signMethod' field. Consequently, the server will read the 'secureKey' from local configuration (line 199 in acp_service.php) and invoke validateBySecureKey() in line 204 to process the message.

Since the 'secureKey' is not set in the configuration file (sdk/acp_sdk.ini) by default, SDKConfig.php (line 111) will return null to acp_service.php (line 199). Nevertheless, acp_service.php does not check whether the returned 'secureKey' is null or not. As a result, the attacker can use null as the 'secureKey' and forge a payment result to cheat the merchant server to shop for free.

On the other hand, the same vulnerability does not exist in UnionPay's SDKs in other languages, namely Java and .NET, as the null key will trigger exceptions in the cases.

Attack Demo

The SDKs from UnionPay include demo pages (in demo/). You may set them up with our online archives to perform a PoC.
To be specific, BackReceive.php in demo/api_01_gateway/ (i.e., http://your_ip/upacp_demo_b2c/demo/api_01_gateway/BackReceive.php) is responsible for processing the payment results. The script invokes validate() in line 45 for verifying the payment message. Once the verification succeeds, the script will print "验签成功" ("Signature Verification Success" in English).

Our PoC code (available at https://www.dropbox.com/s/o8r5yeqwb814pv3/poc.py?dl=0) can send the forged payment results to the BackReceive.php on your machine and will get successful responses, namely "验签成功".

Reference

Contact

Email: mobitec@ie.cuhk.edu.hk
Mobile Technologies Centre (MobiTeC, https://mobitec.ie.cuhk.edu.hk),
Department of Information Engineering,
The Chinese University of Hong Kong