Make WordPress Core


Ignore:
Timestamp:
02/28/2025 06:51:44 PM (11 months ago)
Author:
johnbillion
Message:

Security: Reintroduce support for passwords hashed with MD5.

This reinstates the ability for a user to log in to an account where the password is hashed using MD5. This means that the ability to reset a password directly in the database using an SQL query or a database administration tool will be retained without the need to implement or integrate with bcrypt or phpass.

A password hashed with MD5 will get upgraded to bcrypt at the point where a user successfully logs in, just as is the case with a phpass hash.

Props audrasjb, aaronjorbin, johnbillion, david-innes, benniledl.

See #21022.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/auth.php

    r59828 r59893  
    319319     * @ticket 21022
    320320     */
    321     public function test_wp_check_password_does_not_support_md5_hashes() {
     321    public function test_wp_check_password_supports_md5_hash() {
    322322        $password = 'password';
    323323        $hash     = md5( $password );
    324         $this->assertFalse( wp_check_password( $password, $hash ) );
     324        $this->assertTrue( wp_check_password( $password, $hash ) );
    325325        $this->assertSame( 1, did_filter( 'check_password' ) );
    326326    }
     
    364364    public function data_empty_values() {
    365365        return array(
    366             // Integer zero:
    367             array( 0 ),
    368366            // String zero:
    369367            array( '0' ),
     
    10851083     * @ticket 21022
    10861084     */
     1085    public function test_md5_password_is_rehashed_after_successful_user_password_authentication( $username_or_email ) {
     1086        $password = 'password';
     1087
     1088        // Set the user password with the old md5 algorithm.
     1089        self::set_user_password_with_md5( $password, self::$user_id );
     1090
     1091        // Verify that the password needs rehashing.
     1092        $hash = get_userdata( self::$user_id )->user_pass;
     1093        $this->assertTrue( wp_password_needs_rehash( $hash, self::$user_id ) );
     1094
     1095        // Authenticate.
     1096        $user = wp_authenticate( $username_or_email, $password );
     1097
     1098        // Verify that the md5 password hash was valid.
     1099        $this->assertNotWPError( $user );
     1100        $this->assertInstanceOf( 'WP_User', $user );
     1101        $this->assertSame( self::$user_id, $user->ID );
     1102
     1103        // Verify that the password no longer needs rehashing.
     1104        $hash = get_userdata( self::$user_id )->user_pass;
     1105        $this->assertFalse( wp_password_needs_rehash( $hash, self::$user_id ) );
     1106
     1107        // Authenticate a second time to ensure the new hash is valid.
     1108        $user = wp_authenticate( $username_or_email, $password );
     1109
     1110        // Verify that the bcrypt password hash is valid.
     1111        $this->assertNotWPError( $user );
     1112        $this->assertInstanceOf( 'WP_User', $user );
     1113        $this->assertSame( self::$user_id, $user->ID );
     1114    }
     1115
     1116    /**
     1117     * @dataProvider data_usernames
     1118     *
     1119     * @ticket 21022
     1120     */
    10871121    public function test_bcrypt_password_is_rehashed_with_new_cost_after_successful_user_password_authentication( $username_or_email ) {
    10881122        $password = 'password';
     
    17731807    }
    17741808
     1809    /**
     1810     * Test the tests
     1811     *
     1812     * @covers Tests_Auth::set_user_password_with_md5
     1813     *
     1814     * @ticket 21022
     1815     */
     1816    public function test_set_user_password_with_md5() {
     1817        $password = 'password';
     1818
     1819        // Set the user password with the old md5 algorithm.
     1820        self::set_user_password_with_md5( $password, self::$user_id );
     1821
     1822        // Ensure the password is hashed with md5.
     1823        $hash = get_userdata( self::$user_id )->user_pass;
     1824        $this->assertSame( md5( $password ), $hash );
     1825    }
     1826
     1827    private static function set_user_password_with_md5( string $password, int $user_id ) {
     1828        global $wpdb;
     1829
     1830        $wpdb->update(
     1831            $wpdb->users,
     1832            array(
     1833                'user_pass' => md5( $password ),
     1834            ),
     1835            array(
     1836                'ID' => $user_id,
     1837            )
     1838        );
     1839        clean_user_cache( $user_id );
     1840    }
    17751841
    17761842    /**
Note: See TracChangeset for help on using the changeset viewer.