Go Back   vb.org Archive > vBulletin Modifications > vBulletin 4.x Modifications > vBulletin 4.x Add-ons
FAQ Community Calendar Today's Posts Search

Reply
 
Thread Tools
Secure BCrypt Password Hashing Details »»
Secure BCrypt Password Hashing
Version: 2.00, by MegaManSec MegaManSec is offline
Developer Last Online: Dec 2016 Show Printable Version Email this Page

Category: Mini Mods - Version: 4.x.x Rating:
Released: 09-28-2012 Last Update: Never Installs: 15
Re-useable Code Code Changes Translations  
No support by the author.

This is a 'howto' for using bcrypt for your password hashs, instead of the default vBulletin one, which is highly insecure.

Remember, backup your database before doing this!!

Quote:
bcrypt is a key derivation function for passwords designed by Niels Provos and David Mazi?res, based on the Blowfish cipher, and presented at USENIX in 1999. Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

More information about BCrypt can be found here: http://codahale.com/how-to-safely-store-a-password/ - http://phpmaster.com/why-you-should-...red-passwords/

tl;dr: if you want to be moar secure, use bcrypt.


" How much slower is bcrypt than, say, MD5? Depends on the work factor. Using a work factor of 12, bcrypt hashes the password 'password' in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a nanosecond."


BEFORE YOU DO THIS, PLEASE CREATE A .PHP FILE WITH THIS IN IT
Code:
<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
    echo "CRYPT_BLOWFISH is enabled!";
}
else {
    echo "CRYPT_BLOWFISH is not available";
}
If it is not available, please contact your host.




/includes/functions.php
Add this to the end, just before the footer message.

Code:
/**
 * 
 * Hash 'password' using the crypt() function w/  bcrypt
 * Use the first 21 characters of the MD5(strrev($salt)) as our bcrypt salt
 * Return the MD5 return of this crypt() call, to maintain database functionality. The main part of our security is kept(making hashing, thus cracking, longer).

 * This should always be called like hash_password_bcrypt(md5(md5($password) . $salt), $salt)
 **/
function hash_password_bcrypt($password, $salt) {
       //You may set this to your liking. A higher cost means it will take longer for the password to hash. 15 seems to be a good value.
       $cost = 15; // must be in range 04 - 31

     return md5(crypt($password, '$2y$' . $cost . '$' . substr(md5(strrev($salt)),0,21) . '$'));

}


includes/class_dm_user.php
Now..

Find this:
Code:
                        if ($password == md5(md5($this->fetch_field('username')) . $salt))
and replace it with this:
Code:
                        if ($password == $this->hash_password($this->fetch_field('username'), $salt))
(Note to self.. Why does the original code use this implicit hashing rather than the hash_password function? hash_password takes cares of md5 stuff already if it's not already md5)


Then, on the same file, replace this:
Code:
return md5($password . $salt);
with this
Code:
//No need to md5($password), since it is already md5'd above.
return hash_password_bcrypt(md5($password . $salt), $salt);



includes/functions_login.php


Find this:
Code:
                       $vbulletin->userinfo['password'] != iif($password AND !$md5password, md5(md5($password) . $vbulletin->userinfo['salt']), '') AND
                       $vbulletin->userinfo['password'] != iif($md5password, md5($md5password . $vbulletin->userinfo['salt']), '') AND
                       $vbulletin->userinfo['password'] != iif($md5password_utf, md5($md5password_utf . $vbulletin->userinfo['salt']), '')
And replace it with this:

Code:
                       $vbulletin->userinfo['password'] != iif($password AND !$md5password, hash_password_bcrypt(md5(md5($password) . $vbulletin->userinfo['salt']), $vbulletin->userinfo['salt']), '') AND
                       $vbulletin->userinfo['password'] != iif($md5password, hash_password_bcrypt(md5($md5password . $vbulletin->userinfo['salt']), $vbulletin->userinfo['salt']), '') AND
                       $vbulletin->userinfo['password'] != iif($md5password_utf, hash_password_bcrypt(md5($md5password_utf. $vbulletin->userinfo['salt']), $vbulletin->userinfo['salt']), '')

So effectively, we are hashing the password using the normal vBulletin way of
md5(md5($password) . $vbulletin->userinfo['salt'])
however after doing that, we then run hash_password_bcrypt() around it.

By doing it this way, we can now convert our old hashes to the new bcrypt method.

Create a file called "convert.php", with the contents:
Code:
<?php
require("./global.php");
set_time_limit(0);
ini_set('max_execution_time',0);

$q = $db->query_read("select userid, username, password, salt from user WHERE password != ''");
 
echo "Updating " . $db->num_rows($q) . " accounts.<br />\n";


while($r = $db->fetch_array($q)){
    $db->query_write("UPDATE user SET password = '" . hash_password_bcrypt($r['password'], $r['salt']) . "' WHERE userid = '" . $r['userid'] . "'");
     echo "Updated password for " . htmlspecialchars($r['username']) . "<br />\n";
}
 
echo "Finished.<br />\n";
?>
I recommend running the script in a terminal, however you may be able to run it in a browser. If you run it in the browser, it may time out!

Show Your Support

  • This modification may not be copied, reproduced or published elsewhere without author's permission.
2 благодарности(ей) от:
Brandon Sheley, ChiNa

Comments
  #12  
Old 09-29-2012, 09:05 PM
MegaManSec MegaManSec is offline
 
Join Date: Aug 2011
Posts: 97
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Oh. I see what you mean. I thought you were referring to hash cracking.
MD5 collisions aren't such a problem in vBulletin, really.

+ Also, it would take a lot longer to find a hash collision...
Reply With Quote
  #13  
Old 09-29-2012, 09:07 PM
Adrian Schneider's Avatar
Adrian Schneider Adrian Schneider is offline
 
Join Date: Jul 2004
Posts: 2,528
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

It has nothing to do with vBulletin.

If someone hacks into your server and gets your database dump, they can brute force that to find other possible passwords for your users.

The whole point of BCrypt is to make that impossible by A) being ridiculously slow, and B) being a more crytographically unique hash.
Reply With Quote
  #14  
Old 09-29-2012, 09:10 PM
MegaManSec MegaManSec is offline
 
Join Date: Aug 2011
Posts: 97
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Adrian Schneider View Post
It has nothing to do with vBulletin.

If someone hacks into your server and gets your database dump, they can brute force that to find other possible passwords for your users.

The whole point of BCrypt is to make that impossible by A) being ridiculously slow, and B) being a more crytographically unique hash.
Well, BCrypt is not impossible to brute force, it just takes longer, as you've said.


First of all, if they cracked the MD5, what would they get?
They would get the bcrypt value.
Then what? Then they have to crack that.
That's the pointy.
Reply With Quote
  #15  
Old 09-29-2012, 09:40 PM
MegaManSec MegaManSec is offline
 
Join Date: Aug 2011
Posts: 97
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Adrian Schneider View Post
It has nothing to do with vBulletin.

If someone hacks into your server and gets your database dump, they can brute force that to find other possible passwords for your users.

The whole point of BCrypt is to make that impossible by A) being ridiculously slow, and B) being a more crytographically unique hash.
Wait, so are you talking about:

Dictionary Attacks, or
Rainbow Tables
or hash collisions?

Hash collisions aren't useful, afaik.. they just let you login to your account(or NOT your account) with more than just one password.
Reply With Quote
  #16  
Old 10-02-2012, 10:22 PM
Fluke667 Fluke667 is offline
 
Join Date: Feb 2007
Posts: 107
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

NICE

this rocks
Reply With Quote
  #17  
Old 01-23-2015, 02:58 PM
Skyrider Skyrider is offline
 
Join Date: Feb 2006
Location: Netherlands
Posts: 1,392
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

I have a feeling that after using this, the forums login/reset wise is actually much slower.
Reply With Quote
  #18  
Old 01-23-2015, 03:04 PM
Dave Dave is offline
 
Join Date: May 2010
Posts: 2,583
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Skyrider View Post
I have a feeling that after using this, the forums login/reset wise is actually much slower.
Generating the password hash with BCrypt is a bit slower than MD5, but you shouldn't notice any difference on the average server.

Note: the slower the algorithm (and amount of iterations/cost), the longer it takes to brute force passwords, which is a good thing.
Reply With Quote
  #19  
Old 01-23-2015, 03:24 PM
kh99 kh99 is offline
 
Join Date: Aug 2009
Location: Maine
Posts: 13,185
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Skyrider View Post
I have a feeling that after using this, the forums login/reset wise is actually much slower.
If you look at the second piece of code posted above there's a "cost" factor which can be adjusted so that users don't see an objectionable delay.
Reply With Quote
  #20  
Old 09-06-2015, 10:40 PM
MegaManSec MegaManSec is offline
 
Join Date: Aug 2011
Posts: 97
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Updated with a method to set passwords
Reply With Quote
  #21  
Old 09-30-2015, 01:33 PM
ChiNa ChiNa is offline
 
Join Date: Jul 2012
Posts: 457
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Great Job and a Very good Idea. I have had my friends vB4.x forums hacked where the hackers later Published all forum Users Usernames, Email, and MD5 Password Hashes out in Public. I know by facts that they hacked their way in by decrypting the Admin Password somehow. And NOT by Brute Forcing their way in. We suspected that they got in because of a Custom Skin installed on the forum that was vulnerable.

I am not saying its not possible to Hack or Decrypt a Password by Brute Forcing, But I would rather Secure my forum and Passwords a bit Extra than just leaving the doors open and Welcome them! At least they would use more time to Crack the Passwords.

Thumbs up and Well Done.

Ps, I asssume you could use the same method for vB3.8. So I hope you will create a version for vBulletin 3.8 Users too.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 09:53 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.06979 seconds
  • Memory Usage 2,341KB
  • Queries Executed 26 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (9)bbcode_code
  • (5)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_post
  • (1)navbar
  • (4)navbar_link
  • (120)option
  • (1)pagenav
  • (1)pagenav_curpage
  • (2)pagenav_pagelink
  • (11)post_thanks_box
  • (2)post_thanks_box_bit
  • (11)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (1)post_thanks_postbit
  • (11)post_thanks_postbit_info
  • (10)postbit
  • (11)postbit_onlinestatus
  • (11)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • fetch_musername
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • post_thanks_function_fetch_thanks_bit_start
  • post_thanks_function_show_thanks_date_start
  • post_thanks_function_show_thanks_date_end
  • post_thanks_function_fetch_thanks_bit_end
  • post_thanks_function_fetch_post_thanks_template_start
  • post_thanks_function_fetch_post_thanks_template_end
  • postbit_imicons
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • pagenav_page
  • pagenav_complete
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete