############################## ############################## ##########
# _ ___ _ _ ____ ____ _ _____
# | | / _ \| \ | |/ ___|/ ___| / \|_ _|
# | | | | | | \| | | _| | / _ \ | |
# | |__| |_| | |\ | |_| | |___ / ___ \| |
# |_____\___/|_| \_|\____|\____/_/ \_\_|
#
# 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 =
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA.' mysupersecretpassword';
$pass2 =
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA.'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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA
$pass1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAmysupersecretpassw ord
Hash::make($pass1)
$2y$10$ 9oMcpTwHgTzR5ZUMqlnMMOx/ P18QZ5e9054lq.pwxw1O9urX3JHHu
Hash::check($input, $hash1) Yes
User 2
Desc. Value
$input
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA
$pass2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAlongcatishere
Hash::make($pass2)
$2y$10$ W7wwB4nLmFjrenJGmx1uauqhjzikZN ZA0qzxH8wkbiSmVatCYrAUm
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
//The information contained within this publication is
//supplied "as-is"with no warranties or guarantees of fitness
//of use or otherwise. Bot24, Inc nor Bradley Sean Susser accepts
//responsibility for any damage caused by the use or misuse of
//this information
# _ ___ _ _ ____ ____ _ _____
# | | / _ \| \ | |/ ___|/ ___| / \|_ _|
# | | | | | | \| | | _| | / _ \ | |
# | |__| |_| | |\ | |_| | |___ / ___ \| |
# |_____\___/|_| \_|\____|\____/_/ \_\_|
#
# 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/
#
##############################
[+] 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/
[+] Description
==============================
By using Laravel Security mechanism,
http://laravel.com/docs/
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/
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 =
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$pass2 =
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// 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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$pass1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Hash::make($pass1)
$2y$10$
Hash::check($input, $hash1) Yes
User 2
Desc. Value
$input
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$pass2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Hash::make($pass2)
$2y$10$
Hash::check($input, $hash2) Yes
[+] Vulnerable Code
==============================
/vendor/laravel/framework/src/
...
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.
//The information contained within this publication is
//supplied "as-is"with no warranties or guarantees of fitness
//of use or otherwise. Bot24, Inc nor Bradley Sean Susser accepts
//responsibility for any damage caused by the use or misuse of
//this information