Skip to content

Commit

Permalink
Import external bcrypt plugin for password hashing
Browse files Browse the repository at this point in the history
It was noted in <#216> that
our project template defaults to WordPress default hashing method for
password, which is still in 2024 weak MD5. There has for a long time
existed mu-plugin, which can be used to replace password hashing with
bcrypt.

This plugin hooks to WordPress core password handling functions, and
overrides password checks so all obsolete MD5-hashed passwords will be
converted to bcrypt (or whatever is in future the PHP default password
hashing function).

See source code for more documentation.

Source:
<https://raw.githubusercontent.com/roots/wp-password-bcrypt/master/wp-password-bcrypt.php>
Original commit: <15f0d8919fb3731f79a0cf2fb47e1baecb86cb26>
License: MIT
Author: Roots
Author URI: <https://roots.io>

Closes: #216
  • Loading branch information
ypcs committed Feb 21, 2024
1 parent 78802c9 commit 24ffbac
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ htdocs/wp-content/mu-plugins/*
!htdocs/wp-content/mu-plugins/.gitkeep
!htdocs/wp-content/mu-plugins/register-theme-directory.php
!htdocs/wp-content/mu-plugins/bedrock-autoloader.php
!htdocs/wp-content/mu-plugins/wp-password-bcrypt.php
htdocs/wp-content/themes/twenty*
!htdocs/wp-content/themes/.gitkeep
htdocs/wp-content/languages/*
Expand Down
137 changes: 137 additions & 0 deletions htdocs/wp-content/mu-plugins/wp-password-bcrypt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

/**
* Plugin Name: WP Password bcrypt
* Plugin URI: https://github.com/roots/wp-password-bcrypt
* Description: Replaces wp_hash_password and wp_check_password with password_hash and password_verify.
* Author: Roots
* Author URI: https://roots.io
* Version: 1.1.0
* Licence: MIT
*/

/**
* Determine if the plaintext password matches the encrypted password hash.
*
* If the password hash is not encrypted using the PASSWORD_DEFAULT (bcrypt)
* algorithm, the password will be rehashed and updated once verified.
*
* @link https://www.php.net/manual/en/function.password-verify.php
* @link https://www.php.net/manual/en/function.password-needs-rehash.php
*
* @param string $password The password in plaintext.
* @param string $hash The hashed password to check against.
* @param string|int $user_id The optional user ID.
* @return bool
*
* @SuppressWarnings(PHPMD.CamelCaseVariableName) $wp_hasher
*/
function wp_check_password($password, $hash, $user_id = '')
{
if (! password_needs_rehash($hash, PASSWORD_DEFAULT, apply_filters('wp_hash_password_options', []))) {
return apply_filters(
'check_password',
password_verify($password, $hash),
$password,
$hash,
$user_id
);
}

global $wp_hasher;

if (empty($wp_hasher)) {
require_once ABSPATH . WPINC . '/class-phpass.php';
$wp_hasher = new PasswordHash(8, true);
}

if (! empty($user_id) && $wp_hasher->CheckPassword($password, $hash)) {
$hash = wp_set_password($password, $user_id);
}

return apply_filters(
'check_password',
password_verify($password, $hash),
$password,
$hash,
$user_id
);
}

/**
* Hash the provided password using the PASSWORD_DEFAULT (bcrypt)
* algorithm.
*
* @link https://www.php.net/manual/en/function.password-hash.php
*
* @param string $password The password in plain text.
* @return string
*/
function wp_hash_password($password)
{
return password_hash(
$password,
PASSWORD_DEFAULT,
apply_filters('wp_hash_password_options', [])
);
}

/**
* Hash and update the user's password.
*
* @param string $password The new user password in plaintext.
* @param int $user_id The user ID.
* @return string
*/
function wp_set_password($password, $user_id)
{
$hash = wp_hash_password($password);
$is_api_request = apply_filters(
'application_password_is_api_request',
(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) ||
(defined('REST_REQUEST') && REST_REQUEST)
);

if (! $is_api_request) {
global $wpdb;

$wpdb->update($wpdb->users, [
'user_pass' => $hash,
'user_activation_key' => ''
], ['ID' => $user_id]);

clean_user_cache($user_id);

return $hash;
}

if (
! class_exists('WP_Application_Passwords') ||
empty($passwords = WP_Application_Passwords::get_user_application_passwords($user_id))
) {
return;
}

global $wp_hasher;

if (empty($wp_hasher)) {
require_once ABSPATH . WPINC . '/class-phpass.php';
$wp_hasher = new PasswordHash(8, true);
}

foreach ($passwords as $key => $value) {
if (! $wp_hasher->CheckPassword($password, $value['password'])) {
continue;
}

$passwords[$key]['password'] = $hash;
}

update_user_meta(
$user_id,
WP_Application_Passwords::USERMETA_KEY_APPLICATION_PASSWORDS,
$passwords
);

return $hash;
}

0 comments on commit 24ffbac

Please sign in to comment.