Laravel Encrypter Component Potential Decryption Failure Leading to Unintended Behavior
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
Details
The Laravel Encrypter component is susceptible to a vulnerability that may result in decryption failure, leading to an unexpected return of `false`. Exploiting this issue requires the attacker to manipulate the encrypted payload before decryption. When combined with weak type comparisons in the application's code, such as the example below: ``` <?php $decyptedValue = decrypt($secret); if ($decryptedValue == '') { // Code is run even though decrypted value is false... } ```
The fix
check iv length
src/Illuminate/Encryption/Encrypter.php+2 −3
@@ -206,9 +206,8 @@ protected function getJsonPayload($payload)*/protected function validPayload($payload){-return is_array($payload) && isset(-$payload['iv'], $payload['value'], $payload['mac']-);+return is_array($payload) && isset($payload['iv'], $payload['value'], $payload['mac']) &&+strlen(base64_decode($payload['iv'], true)) === openssl_cipher_iv_length($this->cipher);}/**
check iv length
src/Illuminate/Encryption/Encrypter.php+2 −3
@@ -206,9 +206,8 @@ protected function getJsonPayload($payload)*/protected function validPayload($payload){-return is_array($payload) && isset(-$payload['iv'], $payload['value'], $payload['mac']-);+return is_array($payload) && isset($payload['iv'], $payload['value'], $payload['mac']) &&+strlen(base64_decode($payload['iv'], true)) === openssl_cipher_iv_length($this->cipher);}/**
tests/Encryption/EncrypterTest.php+15 −0
@@ -102,4 +102,19 @@ public function testExceptionThrownWithDifferentKey()$b = new Encrypter(str_repeat('b', 16));$b->decrypt($a->encrypt('baz'));}++/**+* @expectedException \Illuminate\Contracts\Encryption\DecryptException+* @expectedExceptionMessage The payload is invalid.+*/+public function testExceptionThrownWhenIvIsTooLong()+{+$e = new Encrypter(str_repeat('a', 16));+$payload = $e->encrypt('foo');+$data = json_decode(base64_decode($payload), true);+$data['iv'] .= $data['value'][0];+$data['value'] = substr($data['value'], 1);+$modified_payload = base64_encode(json_encode($data));+$e->decrypt($modified_payload);+}}
References
- WEBhttps://github.com/laravel/framework/commit/28e53f23a76206fb130e9a54eb95aa3f010e79c9
- WEBhttps://github.com/laravel/framework/commit/886d261df0854426b4662b7ed5db6a1c575a4279
- WEBhttps://github.com/FriendsOfPHP/security-advisories/blob/master/laravel/framework/2018-03-30-1.yaml
- PACKAGEhttps://github.com/laravel/framework
- WEBhttps://medium.com/@taylorotwell/laravel-security-release-5-6-15-and-5-5-40-56f1257933a0