Skip to content

Instantly share code, notes, and snippets.

@bjornjohansen
Last active February 2, 2017 11:09
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bjornjohansen/d8eaa6793ea05b8d957e7be724b23666 to your computer and use it in GitHub Desktop.
Save bjornjohansen/d8eaa6793ea05b8d957e7be724b23666 to your computer and use it in GitHub Desktop.
Test a bunch of permutations of the password when logging into WordPress.
<?php
/**
* Test a bunch of permutations of the password when logging into WordPress.
*
* Drop this file in your mu-plugins directory.
* Inspired by Facebook: https://twitter.com/gcpascutto/status/821755332984717314/photo/1
* Works with any properly coded hashing pluggables, like Roots’ WP Password bcrypt.
*
* @author bjornjohansen
* @version 0.1.4
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU General Public License version 2 (GPLv2)
* @package Test_Password_Permutations
*/
add_filter( 'check_password', 'test_password_permutations', 20, 4 );
/**
* Try permutations of the password if the login failed.
*
* @param bool $check Whether the passwords match.
* @param string $password The plaintext password.
* @param string $hash The hashed password.
* @param string|int $user_id User ID. Can be empty.
* @return bool False, if none of the $password permutations match the hashed password.
*/
function test_password_permutations( $check, $password, $hash, $user_id ) {
// Don’t run this filter recursively (it is applied in wp_check_password() ).
if ( ! apply_filters( 'enable_password_fixer_filter', true ) ) {
return $check;
}
if ( ! has_filter( 'enable_password_fixer_filter' ) ) {
add_filter( 'enable_password_fixer_filter', '__return_false' );
}
if ( $check ) {
// Password was correct. No need for us to try permutations.
return $check;
}
// Accept password if a user inadverntently has caps lock enabled.
if ( ! $check ) {
// Flip case.
$test_password = '';
for ( $i = 0, $c = mb_strlen( $password ); $i < $c; $i++ ) {
$char = mb_substr( $password, $i, 1 );
if ( mb_strtoupper( $char ) === $char ) {
$test_password .= mb_strtolower( $char );
} else {
$test_password .= mb_strtoupper( $char );
}
}
$check = wp_check_password( $test_password, $hash );
}
// Accept password if their mobile device automatically capitalized the first character of the password.
if ( ! $check ) {
$test_password = mb_strtolower( mb_substr( $password, 0, 1 ) ) . mb_substr( $password, 1 );
// Only test if the permutation actually changed the password.
if ( $test_password !== $password ) {
$check = wp_check_password( $test_password, $hash );
}
}
// Accept password if an extra character is added to the end of the password.
if ( ! $check ) {
$test_password = mb_substr( $password, 0, mb_strlen( $password ) -1 );
// Only test if the permutation actually changed the password.
if ( $test_password !== $password ) {
$check = wp_check_password( $test_password, $hash );
}
}
// Trim whitespaces from both ends of the password.
if ( ! $check ) {
$test_password = trim( $password );
// Only test if the permutation actually changed the password.
if ( $test_password !== $password ) {
$check = wp_check_password( $test_password, $hash );
}
}
return $check;
}
@bjornjohansen
Copy link
Author

I have written a post on the subject that explains this more, and with some password security math: https://bjornjohansen.no/wordpress-assisted-password-check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment