Make WordPress Core


Ignore:
Timestamp:
07/01/2015 06:32:07 AM (9 years ago)
Author:
dd32
Message:

Expire password reset links after 24 hours (by default). This causes existing password reset links to become invalid.

Props markjaquith, voldemortensen, johnbillion, MikeHansenMe, dd32
See #32429

File:
1 edited

Legend:

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

    r32785 r33019  
    77class Tests_Auth extends WP_UnitTestCase {
    88    var $user_id;
     9    var $wp_hasher;
    910
    1011    function setUp() {
    1112        parent::setUp();
    1213        $this->user_id = $this->factory->user->create();
     14
     15        require_once ABSPATH . WPINC . '/class-phpass.php';
     16        $this->wp_hasher = new PasswordHash( 8, true );
    1317    }
    1418
     
    160164        $this->assertInstanceOf( 'WP_Error', $user );
    161165    }
     166
     167    /**
     168     * @ticket 32429
     169     */
     170    function test_user_activation_key_is_checked() {
     171        global $wpdb;
     172
     173        $key  = wp_generate_password( 20, false );
     174        $user = $this->factory->user->create_and_get();
     175        $wpdb->update( $wpdb->users, array(
     176            'user_activation_key' => strtotime( '-1 hour' ) . ':' . $this->wp_hasher->HashPassword( $key ),
     177        ), array(
     178            'ID' => $user->ID,
     179        ) );
     180
     181        // A valid key should be accepted
     182        $check = check_password_reset_key( $key, $user->user_login );
     183        $this->assertInstanceOf( 'WP_User', $check );
     184        $this->assertSame( $user->ID, $check->ID );
     185
     186        // An invalid key should be rejected
     187        $check = check_password_reset_key( 'key', $user->user_login );
     188        $this->assertInstanceOf( 'WP_Error', $check );
     189
     190        // An empty key should be rejected
     191        $check = check_password_reset_key( '', $user->user_login );
     192        $this->assertInstanceOf( 'WP_Error', $check );
     193
     194        // A truncated key should be rejected
     195        $partial = substr( $key, 0, 10 );
     196        $check = check_password_reset_key( $partial, $user->user_login );
     197        $this->assertInstanceOf( 'WP_Error', $check );
     198    }
     199
     200    /**
     201     * @ticket 32429
     202     */
     203    function test_expired_user_activation_key_is_rejected() {
     204        global $wpdb;
     205
     206        $key  = wp_generate_password( 20, false );
     207        $user = $this->factory->user->create_and_get();
     208        $wpdb->update( $wpdb->users, array(
     209            'user_activation_key' => strtotime( '-48 hours' ) . ':' . $this->wp_hasher->HashPassword( $key ),
     210        ), array(
     211            'ID' => $user->ID,
     212        ) );
     213
     214        // An expired but otherwise valid key should be rejected
     215        $check = check_password_reset_key( $key, $user->user_login );
     216        $this->assertInstanceOf( 'WP_Error', $check );
     217    }
     218
     219    /**
     220     * @ticket 32429
     221     */
     222    function test_empty_user_activation_key_fails_key_check() {
     223        global $wpdb;
     224
     225        $user = $this->factory->user->create_and_get();
     226
     227        // An empty user_activation_key should not allow any key to be accepted
     228        $check = check_password_reset_key( 'key', $user->user_login );
     229        $this->assertInstanceOf( 'WP_Error', $check );
     230
     231        // An empty user_activation_key should not allow an empty key to be accepted
     232        $check = check_password_reset_key( '', $user->user_login );
     233        $this->assertInstanceOf( 'WP_Error', $check );
     234    }
     235
     236    /**
     237     * @ticket 32429
     238     */
     239    function test_legacy_user_activation_key_is_rejected() {
     240        global $wpdb;
     241
     242        // A legacy user_activation_key is one without the `time()` prefix introduced in WordPress 4.3.
     243
     244        $key  = wp_generate_password( 20, false );
     245        $user = $this->factory->user->create_and_get();
     246        $wpdb->update( $wpdb->users, array(
     247            'user_activation_key' => $this->wp_hasher->HashPassword( $key ),
     248        ), array(
     249            'ID' => $user->ID,
     250        ) );
     251
     252        // A legacy user_activation_key should not be accepted
     253        $check = check_password_reset_key( $key, $user->user_login );
     254        $this->assertInstanceOf( 'WP_Error', $check );
     255
     256        // An empty key with a legacy user_activation_key should be rejected
     257        $check = check_password_reset_key( '', $user->user_login );
     258        $this->assertInstanceOf( 'WP_Error', $check );
     259    }
     260
     261    /**
     262     * @ticket 32429
     263     * @ticket 24783
     264     */
     265    function test_plaintext_user_activation_key_is_rejected() {
     266        global $wpdb;
     267
     268        // A plaintext user_activation_key is one stored before hashing was introduced in WordPress 3.7.
     269
     270        $key  = wp_generate_password( 20, false );
     271        $user = $this->factory->user->create_and_get();
     272        $wpdb->update( $wpdb->users, array(
     273            'user_activation_key' => $key,
     274        ), array(
     275            'ID' => $user->ID,
     276        ) );
     277
     278        // A plaintext user_activation_key should not allow an otherwise valid key to be accepted
     279        $check = check_password_reset_key( $key, $user->user_login );
     280        $this->assertInstanceOf( 'WP_Error', $check );
     281
     282        // A plaintext user_activation_key should not allow an empty key to be accepted
     283        $check = check_password_reset_key( '', $user->user_login );
     284        $this->assertInstanceOf( 'WP_Error', $check );
     285    }
    162286}
Note: See TracChangeset for help on using the changeset viewer.