VYPR
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.

PackageAffected versionsPatched versions
simplesamlphp/simplesamlphpPackagist
< 1.14.131.14.13

Affected products

1

Patches

1
4c939be1696b

Make sure data encrypted with SimpleSAML\Utils\Crypto::aesEncrypt() is also authenticated.

https://github.com/simplesamlphp/simplesamlphpJaime Pérez CrespoApr 26, 2017via ghsa
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

News mentions

0

No linked articles in our index yet.