Laravel 2.1 Hash::make() bcrypt Truncation

2014.09.17
Credit: u0x
Risk: Medium
Local: Yes
Remote: No
CVE: N/A
CWE: N/A

###################################################################### # _ ___ _ _ ____ ____ _ _____ # | | / _ \| \ | |/ ___|/ ___| / \|_ _| # | | | | | | \| | | _| | / _ \ | | # | |__| |_| | |\ | |_| | |___ / ___ \| | # |_____\___/|_| \_|\____|\____/_/ \_\_| # # Laravel 2.1 Hash::make() bcrypt truncation # Website : http://laravel.com/ # Author : @u0x (Pichaya Morimoto) # Release dates : September 16, 2014 # # Special Thanks to 2600 Thailand group # https://www.facebook.com/groups/2600Thailand/ , http://2600.in.th/ # ######################################################################## [+] Laravel ============================================================ Laravel is a free, open source PHP web application framework, designed for the development of model–view–controller (MVC) web applications. According to a December 2013 developers survey on PHP frameworks popularity, Laravel is listed as the most popular PHP framework in 2013. At the same time, as of August 2014 Laravel is the most popular and watched PHP project on GitHub. https://en.wikipedia.org/wiki/Laravel [+] Description ============================================================ By using Laravel Security mechanism, http://laravel.com/docs/security#storing-passwords The passwords will be hashed using Laravel's Hash::make() function. This function internally call PHP 's password_hash() without checking the length. Why do we need to check length? as PHP manual said, "Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters." http://php.net/manual/en/function.password-hash.php The problem occurs if users enter password longer than 72 characters then the password will be truncated to be 72 characters. This will result in pseudo hash collision. [+] Proof-of-Concept ============================================================ // user input password $input = str_repeat('A',72); // plaintext password $pass1 = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.'mysupersecretpassword'; $pass2 = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.'longcatishere'; // hashed password $hash1 = Hash::make($pass1); $hash2 = Hash::make($pass2); // match? $status1 = Hash::check($input, $hash1)?'Yes':'No'; $status2 = Hash::check($input, $hash2)?'Yes':'No'; User 1 Desc. Value $input AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $pass1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmysupersecretpassword Hash::make($pass1) $2y$10$9oMcpTwHgTzR5ZUMqlnMMOx/P18QZ5e9054lq.pwxw1O9urX3JHHu Hash::check($input, $hash1) Yes User 2 Desc. Value $input AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $pass2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlongcatishere Hash::make($pass2) $2y$10$W7wwB4nLmFjrenJGmx1uauqhjzikZNZA0qzxH8wkbiSmVatCYrAUm Hash::check($input, $hash2) Yes [+] Vulnerable Code ============================================================ /vendor/laravel/framework/src/Illuminate/Hashing/BcryptHasher.php ... public function make($value, array $options = array()) { ... $hash = password_hash($value, PASSWORD_BCRYPT, array('cost' => $cost)); ... return $hash; [+] How to fix this? ============================================================ In Django project, they solved this problem by applying SHA256 before using bcrypt "BCryptSHA256PasswordHasher fixes this by first hashing the password using sha256. This prevents the password truncation" https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-bcrypt-with-django


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top