CVE-2026-14355
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().
A Buffer Overflow vulnerability (CVE-2026-14355) has been identified in openssl_encrypt(), part of PHP's OpenSSL extension, which allows an attacker who can influence the data, or the choice of cipher, that an application encrypts with an AES key wrap with padding cipher (aes-*-wrap-pad) to make OpenSSL write past the end of a heap buffer, corrupting heap memory and typically aborting the process. PHP tracks this issue as GHSA-7jrw-539f-x6vr.
Per MITRE CWE-122: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
This issue affects all versions of PHP before 8.2.32, PHP 8.3 before 8.3.32, PHP 8.4 before 8.4.23 and PHP 8.5 before 8.5.8, which includes every release of the End-of-Life PHP 5.6, 7.0 through 7.4, 8.0 and 8.1 release lines, when built against an OpenSSL version that allows key wrap with padding through openssl_encrypt().
Details
Module Info
- Product: PHP
- Affected packages:
php-src(ext/openssl) - Affected versions: <8.2.32, >=8.3.0 <8.3.32, >=8.4.0 <8.4.23, >=8.5.0 <8.5.8
- GitHub repository: https://github.com/php/php-src
- Published packages: https://www.php.net/downloads
- Package manager: N/A
- Fixed in:
- OSS PHP 8.2.32, 8.3.32, 8.4.23, 8.5.8
- NES for PHP 5.6.1 (based on PHP 5.6.40)
- NES for PHP 7.2.1 (based on PHP 7.2.34)
- NES for PHP 7.4.1 (based on PHP 7.4.33)
Vulnerability Info
This Medium-severity vulnerability is found in the openssl extension of all versions of PHP before 8.2.32, PHP 8.3 before 8.3.32, PHP 8.4 before 8.4.23 and PHP 8.5 before 8.5.8, including the End-of-Life PHP 5.6, 7.0 through 7.4, 8.0 and 8.1 release lines, which never received the upstream fix. The PHP project scores it 5.6 under CVSS 3.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L).
Before it calls OpenSSL, openssl_encrypt() allocates an output buffer of the input length plus one cipher block, which is enough for ordinary block cipher modes. AES key wrap with padding (RFC 5649) works differently: it rounds the input up to the block size and adds an integrity block, so OpenSSL can write up to one more block than PHP reserved. In PHP 7.4.33, php_openssl_cipher_update() sizes the buffer like this:
*poutbuf = zend_string_alloc((int)data_len + EVP_CIPHER_block_size(cipher_type), 0);
if (!EVP_CipherUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(*poutbuf),
&i, (unsigned char *)data, (int)data_len)) {
With an aes-*-wrap-pad cipher, OpenSSL then writes up to 8 bytes past the end of the heap block, which corrupts heap metadata and can abort the PHP process. The CVE record rates the confidentiality, integrity and availability impact as low.
Exploitation needs an application that encrypts data with an AES key wrap with padding cipher through openssl_encrypt(), or that lets an attacker choose the cipher name or the data for such a cipher. Any SAPI is affected. Whether a build is exposed depends on its OpenSSL version. HeroDevs' analysis found that builds against OpenSSL 3 are exposed, while the OpenSSL 1.0 and 1.1 builds it tested either lack the wrap-with-padding cipher or refuse wrap ciphers in openssl_encrypt(). On PHP 5.6, which went on using a refused, unkeyed cipher context, those older builds could still crash or read an uninitialized key schedule.
The upstream fix, by David Carlier, reserves one more block when the cipher is in wrap mode:
#ifdef EVP_CIPH_WRAP_MODE
if ((EVP_CIPHER_mode(cipher_type)) == EVP_CIPH_WRAP_MODE) {
/*
* RFC 5649 wrap-with-padding rounds the input up to the block size
* and prepends an integrity block, we reserve one extra block.
* See EVP_EncryptUpdate(3): wrap mode may write up to
* inl + cipher_block_size bytes.
*/
outlen += EVP_CIPHER_block_size(cipher_type);
}
#endif
NES for PHP carries the fix to PHP 5.6, 7.2 and 7.4. On PHP 5.6 it also computes the buffer size without int overflow, and makes openssl_encrypt() and openssl_decrypt() return false when OpenSSL refuses a cipher, as PHP 7.1 and later do.
Mitigation
The PHP project publishes security fixes only for its supported release lines. PHP 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0 and 8.1 are End-of-Life and will not receive any public updates to address this issue.
Until an upgrade is possible, do not use aes-*-wrap-pad ciphers with openssl_encrypt(), and do not let untrusted input choose the cipher name.
Users of the affected components should apply one of the following mitigations:
- Upgrade to PHP 8.2.32, 8.3.32, 8.4.23, 8.5.8, or later.
- Leverage a commercial support partner like HeroDevs (NES for PHP) for post-EOL security support.
Credits
- Oleg Baturin (finder)
- David Carlier (remediation)