Medium severity5.9NVD Advisory· Published Sep 1, 2017· Updated May 13, 2026
CVE-2017-12870
CVE-2017-12870
Description
SimpleSAMLphp 1.14.12 and earlier make it easier for man-in-the-middle attackers to obtain sensitive information by leveraging use of the aesEncrypt and aesDecrypt methods in the SimpleSAML/Utils/Crypto class to protect session identifiers in replies to non-HTTPS service providers.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
simplesamlphp/simplesamlphpPackagist | < 1.14.13 | 1.14.13 |
Affected products
1Patches
14c939be1696bMake sure data encrypted with SimpleSAML\Utils\Crypto::aesEncrypt() is also authenticated.
2 files changed · +47 −18
lib/SimpleSAML/Utils/Crypto.php+46 −17 modified@@ -13,7 +13,7 @@ class Crypto /** * Decrypt data using AES-256-CBC and the key provided as a parameter. * - * @param string $ciphertext The IV and the encrypted data, concatenated. + * @param string $ciphertext The HMAC of the encrypted data, the IV used and the encrypted data, concatenated. * @param string $secret The secret to use to decrypt the data. * * @return string The decrypted data. @@ -31,21 +31,36 @@ private static function _aesDecrypt($ciphertext, $secret) throw new \SimpleSAML_Error_Exception("The openssl PHP module is not loaded."); } - $raw = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true; - $key = openssl_digest($secret, 'sha256'); - $method = 'AES-256-CBC'; - $ivSize = 16; - $iv = substr($ciphertext, 0, $ivSize); - $data = substr($ciphertext, $ivSize); + // derive encryption and authentication keys from the secret + $key = openssl_digest($secret, 'sha512'); + + $hmac = mb_substr($ciphertext, 0, 32, '8bit'); + $iv = mb_substr($ciphertext, 32, 16, '8bit'); + $msg = mb_substr($ciphertext, 48, mb_strlen($ciphertext, '8bit') - 48, '8bit'); + + // authenticate the ciphertext + if (self::secureCompare(hash_hmac('sha256', $iv.$msg, substr($key, 64, 64), true), $hmac)) { + $plaintext = openssl_decrypt( + $msg, + 'AES-256-CBC', + substr($key, 0, 64), + defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true, + $iv + ); + + if ($plaintext != false) { + return $plaintext; + } + } - return openssl_decrypt($data, $method, $key, $raw, $iv); + throw new \SimpleSAML_Error_Exception("Failed to decrypt ciphertext."); } /** * Decrypt data using AES-256-CBC and the system-wide secret salt as key. * - * @param string $ciphertext The IV used and the encrypted data, concatenated. + * @param string $ciphertext The HMAC of the encrypted data, the IV used and the encrypted data, concatenated. * * @return string The decrypted data. * @htorws \InvalidArgumentException If $ciphertext is not a string. @@ -66,7 +81,7 @@ public static function aesDecrypt($ciphertext) * @param string $data The data to encrypt. * @param string $secret The secret to use to encrypt the data. * - * @return string The IV and encrypted data concatenated. + * @return string An HMAC of the encrypted data, the IV and the encrypted data, concatenated. * @throws \InvalidArgumentException If $data is not a string. * @throws \SimpleSAML_Error_Exception If the openssl module is not loaded. * @@ -82,13 +97,27 @@ private static function _aesEncrypt($data, $secret) throw new \SimpleSAML_Error_Exception('The openssl PHP module is not loaded.'); } - $raw = defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true; - $key = openssl_digest($secret, 'sha256'); - $method = 'AES-256-CBC'; - $ivSize = 16; - $iv = openssl_random_pseudo_bytes($ivSize); + // derive encryption and authentication keys from the secret + $key = openssl_digest($secret, 'sha512'); + + // generate a random IV + $iv = openssl_random_pseudo_bytes(16); + + // encrypt the message + $ciphertext = $iv.openssl_encrypt( + $data, + 'AES-256-CBC', + substr($key, 0, 64), + defined('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true, + $iv + ); + + if ($ciphertext === false) { + throw new \SimpleSAML_Error_Exception("Failed to encrypt plaintext."); + } - return $iv.openssl_encrypt($data, $method, $key, $raw, $iv); + // return the ciphertext with proper authentication + return hash_hmac('sha256', $ciphertext, substr($key, 64, 64), true).$ciphertext; } @@ -97,7 +126,7 @@ private static function _aesEncrypt($data, $secret) * * @param string $data The data to encrypt. * - * @return string The IV and encrypted data concatenated. + * @return string An HMAC of the encrypted data, the IV and the encrypted data, concatenated. * @throws \InvalidArgumentException If $data is not a string. * @throws \SimpleSAML_Error_Exception If the openssl module is not loaded. *
tests/lib/SimpleSAML/Utils/CryptoTest.php+1 −1 modified@@ -50,7 +50,7 @@ public function testAesDecrypt() $m->setAccessible(true); $plaintext = 'SUPER_SECRET_TEXT'; - $ciphertext = 'NmRkODJlZGE2OTA3YTYwMm9En+KAReUk2z7Xi/b3c39kF/c1n6Vdj/zNARQt+UHU'; + $ciphertext = 'uR2Yu0r4itInKx91D/l9y/08L5CIQyev9nAr27fh3Sshous4vbXRRcMcjqHDOrquD+2vqLyw7ygnbA9jA9TpB4hLZocvAWcTN8tyO82hiSY='; $this->assertEquals($plaintext, $m->invokeArgs(null, array(base64_decode($ciphertext), $secret))); }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- simplesamlphp.org/security/201704-01nvdPatchVendor AdvisoryWEB
- github.com/advisories/GHSA-44pr-mgcp-v36rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-12870ghsaADVISORY
- github.com/FriendsOfPHP/security-advisories/blob/master/simplesamlphp/simplesamlphp/CVE-2017-12870.yamlghsaWEB
- github.com/simplesamlphp/simplesamlphp/commit/4c939be1696bacb2b95ee11d4ebc5814a08b04c5ghsaWEB
News mentions
0No linked articles in our index yet.