CVE-2020-7069

Improper Input Validation (4.16)
Affects
PHP
in
PHP
No items found.
Versions
>=7.1.0 <7.2.34, >=7.3.0 <7.3.23, >=7.4.0 <7.4.11

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

PHP is a general-purpose scripting language used mostly for web development. It runs behind web servers through server APIs such as Apache mod_php and PHP-FPM, and powers content management systems and frameworks such as WordPress, Drupal, Moodle and Laravel. Its openssl extension exposes OpenSSL's symmetric ciphers to PHP code through openssl_encrypt() and openssl_decrypt(), including authenticated (AEAD) modes such as AES-GCM and AES-CCM.

An Improper Input Validation vulnerability (CVE-2020-7069) has been identified in the openssl extension of PHP, which causes openssl_encrypt() and openssl_decrypt() to use only the first 7 bytes of a 12-byte initialization vector (IV) with an AES-CCM cipher. This produces ciphertext and tags that other CCM implementations do not accept, and can make different IVs that share their first 7 bytes collide, which weakens the encryption. PHP tracks this issue as bug #79601.

Per MITRE CWE-20: The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

This issue affects PHP 7.1 through its final release (7.1.33), PHP 7.2 before 7.2.34, PHP 7.3 before 7.3.23 and PHP 7.4 before 7.4.11. PHP 5.6 and 7.0 are not affected, because openssl_encrypt() gained support for AEAD ciphers such as AES-CCM in PHP 7.1.

Details

Module Info

Vulnerability Info

This Medium-severity vulnerability is found in the openssl extension of PHP 7.1 through its final release (7.1.33), PHP 7.2 before 7.2.34, PHP 7.3 before 7.3.23 and PHP 7.4 before 7.4.11, including the End-of-Life PHP 7.1 release line, which never received the upstream fix. The PHP project scores it 5.4 under CVSS 3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N).

AES-CCM accepts a nonce, passed to openssl_encrypt() and openssl_decrypt() as the IV, of 7 to 13 bytes. OpenSSL reports 12 bytes as the IV length for its AES-CCM ciphers, but a CCM context uses a 7-byte nonce unless the caller sets the length explicitly with EVP_CTRL_CCM_SET_IVLEN. Before PHP passes the IV to OpenSSL, php_openssl_validate_iv() checks its length. In PHP 7.1.33, the code reads:

static int php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_required_len,
        zend_bool *free_iv, EVP_CIPHER_CTX *cipher_ctx, struct php_openssl_cipher_mode *mode) /* {{{ */
{
    char *iv_new;

    /* Best case scenario, user behaved */
    if (*piv_len == iv_required_len) {
        return SUCCESS;
    }

    if (mode->is_aead) {
        if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) != 1) {
            php_error_docref(NULL, E_WARNING, "Setting of IV length for AEAD mode failed");
            return FAILURE;
        }
        return SUCCESS;
    }

When the IV is exactly the length OpenSSL reports, the function returns before the AEAD branch, so PHP never sets the IV length on the CCM context. OpenSSL then keeps its default 7-byte nonce and ignores the last 5 bytes of the IV. The reporter showed that a 12-byte IV from the NIST SP 800-38C test vectors produced the same ciphertext and tag as the first 7 bytes of that IV alone, instead of the published values. IVs of other lengths take the AEAD branch and are handled correctly.

Data that PHP encrypts with AES-CCM and a 12-byte IV can't be decrypted by other CCM implementations, and PHP can't decrypt their output. More importantly, any two 12-byte IVs that share their first 7 bytes are treated as the same nonce. Applications that build nonces from a fixed prefix and a counter or random value in the last bytes may reuse a nonce under the same key, which can let an attacker who sees the ciphertexts learn about the plaintexts or forge messages.

Only code that calls openssl_encrypt() or openssl_decrypt() with an aes-128-ccm, aes-192-ccm or aes-256-ccm cipher and a 12-byte IV is affected. AES-GCM, other cipher modes and CCM with other IV lengths are not affected.

The fix moves the AEAD branch ahead of the length check, so PHP always sets the IV length for AEAD ciphers:

    char *iv_new;

    if (mode->is_aead) {
        if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) != 1) {
            php_error_docref(NULL, E_WARNING, "Setting of IV length for AEAD mode failed");
            return FAILURE;
        }
        return SUCCESS;
    }

    /* Best case scenario, user behaved */
    if (*piv_len == iv_required_len) {
        return SUCCESS;
    }

Mitigation

The PHP project publishes security fixes only for its supported release lines. PHP 7.1 is End-of-Life and will not receive any public updates to address this issue.

Until an upgrade is possible, applications can use AES-GCM instead of AES-CCM, or pass a CCM IV whose length is not 12 bytes (for example 13 bytes), which takes the code path that sets the IV length correctly. Data already encrypted with a 12-byte IV used only its first 7 bytes, so it may need to be re-encrypted after the upgrade.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to PHP 7.2.34, 7.3.23, 7.4.11, or later.
  • Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
Medium
ID
CVE-2020-7069
PROJECT Affected
PHP
Versions Affected
>=7.1.0 <7.2.34, >=7.3.0 <7.3.23, >=7.4.0 <7.4.11
NES Versions Affected
Published date
October 2, 2020
≈ Fix date
October 1, 2020
Fixed in
Category
Improper Input Validation (4.16)
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
PHP
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.