diff options
Diffstat (limited to 'debian/patches/38474.patch')
-rw-r--r-- | debian/patches/38474.patch | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/debian/patches/38474.patch b/debian/patches/38474.patch new file mode 100644 index 0000000..e7bfee8 --- /dev/null +++ b/debian/patches/38474.patch @@ -0,0 +1,281 @@ +Description: Use hash for user activation key + Removes cleartext of the user activation key + CVE-2017-14990 +Author: timdxw +Origin: upstream, https://core.trac.wordpress.org/ticket/38474 +Bug-Debian: https://bugs.debian.org/877629 +Reviewed-by: Craig Small <csmall@debian.org> +Last-Update: 2023-08-10 +--- a/wp-activate.php ++++ b/wp-activate.php +@@ -42,13 +42,15 @@ + wp_safe_redirect( $redirect_url ); + exit; + } else { +- $result = wpmu_activate_signup( $key ); ++ $signup_id = ! empty( $_GET['signup_id'] ) ? $_GET['signup_id'] : $_POST['signup_id']; ++ $result = wpmu_activate_signup( $key, $signup_id ); + } + } + + if ( null === $result && isset( $_COOKIE[ $activate_cookie ] ) ) { + $key = $_COOKIE[ $activate_cookie ]; +- $result = wpmu_activate_signup( $key ); ++ $signup_id = ! empty( $_GET['signup_id'] ) ? $_GET['signup_id'] : $_POST['signup_id']; ++ $result = wpmu_activate_signup( $key, $signup_id ); + setcookie( $activate_cookie, ' ', time() - YEAR_IN_SECONDS, $activate_path, COOKIE_DOMAIN, is_ssl(), true ); + } + +@@ -133,6 +135,10 @@ + <label for="key"><?php _e( 'Activation Key:' ); ?></label> + <br /><input type="text" name="key" id="key" value="" size="50" autofocus="autofocus" /> + </p> ++ <p> ++ <label for="key"><?php _e( 'Signup ID:' ) ?></label> ++ <br /><input type="number" name="signup_id" id="signup_id" value="" size="50" /> ++ </p> + <p class="submit"> + <input id="submit" type="submit" name="Submit" class="submit" value="<?php esc_attr_e( 'Activate' ); ?>" /> + </p> +--- a/wp-admin/user-new.php ++++ b/wp-admin/user-new.php +@@ -227,8 +227,8 @@ + ) + ); + if ( isset( $_POST['noconfirmation'] ) && current_user_can( 'manage_network_users' ) ) { +- $key = $wpdb->get_var( $wpdb->prepare( "SELECT activation_key FROM {$wpdb->signups} WHERE user_login = %s AND user_email = %s", $new_user_login, $new_user_email ) ); +- $new_user = wpmu_activate_signup( $key ); ++ $row = $wpdb->get_row( $wpdb->prepare( "SELECT activation_key, signup_id FROM {$wpdb->signups} WHERE user_login = %s AND user_email = %s", $new_user_login, $new_user_email ) ); ++ $new_user = wpmu_activate_signup( $row['activation_key'], $row['signup_id'] ); + if ( is_wp_error( $new_user ) ) { + $redirect = add_query_arg( array( 'update' => 'addnoconfirmation' ), 'user-new.php' ); + } elseif ( ! is_user_member_of_blog( $new_user['user_id'] ) ) { +--- a/wp-includes/ms-default-filters.php ++++ b/wp-includes/ms-default-filters.php +@@ -26,7 +26,7 @@ + add_action( 'wpmu_new_user', 'newuser_notify_siteadmin' ); + add_action( 'wpmu_activate_user', 'add_new_user_to_blog', 10, 3 ); + add_action( 'wpmu_activate_user', 'wpmu_welcome_user_notification', 10, 3 ); +-add_action( 'after_signup_user', 'wpmu_signup_user_notification', 10, 4 ); ++add_action( 'after_signup_user', 'wpmu_signup_user_notification', 10, 5 ); + add_action( 'network_site_new_created_user', 'wp_send_new_user_notifications' ); + add_action( 'network_site_users_created_user', 'wp_send_new_user_notifications' ); + add_action( 'network_user_new_created_user', 'wp_send_new_user_notifications' ); +@@ -39,7 +39,7 @@ + // Blogs. + add_filter( 'wpmu_validate_blog_signup', 'signup_nonce_check' ); + add_action( 'wpmu_activate_blog', 'wpmu_welcome_notification', 10, 5 ); +-add_action( 'after_signup_site', 'wpmu_signup_blog_notification', 10, 7 ); ++add_action( 'after_signup_site', 'wpmu_signup_blog_notification', 10, 8 ); + add_filter( 'wp_normalize_site_data', 'wp_normalize_site_data', 10, 1 ); + add_action( 'wp_validate_site_data', 'wp_validate_site_data', 10, 3 ); + add_action( 'wp_insert_site', 'wp_maybe_update_network_site_counts_on_update', 10, 1 ); +--- a/wp-includes/ms-functions.php ++++ b/wp-includes/ms-functions.php +@@ -783,10 +783,17 @@ + * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. + */ + function wpmu_signup_blog( $domain, $path, $title, $user, $user_email, $meta = array() ) { +- global $wpdb; ++ global $wpdb, $wp_hasher; + + $key = substr( md5( time() . wp_rand() . $domain ), 0, 16 ); + ++ if ( empty( $wp_hasher ) ) { ++ require_once ABSPATH . WPINC . '/class-phpass.php'; ++ $wp_hasher = new PasswordHash( 8, true ); ++ } ++ ++ $hashed = time() . ':' . $wp_hasher->HashPassword( $key ); ++ + /** + * Filters the metadata for a site signup. + * +@@ -801,8 +808,9 @@ + * @param string $user The user's requested login name. + * @param string $user_email The user's email address. + * @param string $key The user's activation key. ++ * @param string $hashed The user's hashed activation key. + */ +- $meta = apply_filters( 'signup_site_meta', $meta, $domain, $path, $title, $user, $user_email, $key ); ++ $meta = apply_filters( 'signup_site_meta', $meta, $domain, $path, $title, $user, $user_email, $key, $hashed ); + + $wpdb->insert( + $wpdb->signups, +@@ -813,7 +821,7 @@ + 'user_login' => $user, + 'user_email' => $user_email, + 'registered' => current_time( 'mysql', true ), +- 'activation_key' => $key, ++ 'activation_key' => $hashed, + 'meta' => serialize( $meta ), + ) + ); +@@ -830,8 +838,10 @@ + * @param string $user_email The user's email address. + * @param string $key The user's activation key. + * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. ++ * @param int $signup_id Signup ID. ++ * @param string $hashed The user's hashed activation key. + */ +- do_action( 'after_signup_site', $domain, $path, $title, $user, $user_email, $key, $meta ); ++ do_action( 'after_signup_site', $domain, $path, $title, $user, $user_email, $key, $meta, $wpdb->insert_id, $hashed ); + } + + /** +@@ -849,13 +859,20 @@ + * @param array $meta Optional. Signup meta data. Default empty array. + */ + function wpmu_signup_user( $user, $user_email, $meta = array() ) { +- global $wpdb; ++ global $wpdb, $wp_hasher; + + // Format data. + $user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) ); + $user_email = sanitize_email( $user_email ); + $key = substr( md5( time() . wp_rand() . $user_email ), 0, 16 ); + ++ if ( empty( $wp_hasher ) ) { ++ require_once ABSPATH . WPINC . '/class-phpass.php'; ++ $wp_hasher = new PasswordHash( 8, true ); ++ } ++ ++ $hashed = time() . ':' . $wp_hasher->HashPassword( $key ); ++ + /** + * Filters the metadata for a user signup. + * +@@ -867,8 +884,9 @@ + * @param string $user The user's requested login name. + * @param string $user_email The user's email address. + * @param string $key The user's activation key. ++ * @param string $hashed The user's hashed activation key. + */ +- $meta = apply_filters( 'signup_user_meta', $meta, $user, $user_email, $key ); ++ $meta = apply_filters( 'signup_user_meta', $meta, $user, $user_email, $key, $hashed ); + + $wpdb->insert( + $wpdb->signups, +@@ -879,7 +897,7 @@ + 'user_login' => $user, + 'user_email' => $user_email, + 'registered' => current_time( 'mysql', true ), +- 'activation_key' => $key, ++ 'activation_key' => $hashed, + 'meta' => serialize( $meta ), + ) + ); +@@ -893,8 +911,10 @@ + * @param string $user_email The user's email address. + * @param string $key The user's activation key. + * @param array $meta Signup meta data. Default empty array. ++ * @param int $signup_id Signup ID. ++ * @param string $hashed The user's hashed activation key. + */ +- do_action( 'after_signup_user', $user, $user_email, $key, $meta ); ++ do_action( 'after_signup_user', $user, $user_email, $key, $meta, $wpdb->insert_id, $hashed ); + } + + /** +@@ -920,9 +940,10 @@ + * @param string $user_email The user's email address. + * @param string $key The activation key created in wpmu_signup_blog(). + * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. ++ * @param int $signup_id Signup ID. + * @return bool + */ +-function wpmu_signup_blog_notification( $domain, $path, $title, $user_login, $user_email, $key, $meta = array() ) { ++function wpmu_signup_blog_notification( $domain, $path, $title, $user_login, $user_email, $key, $meta = array(), $signup_id ) { + /** + * Filters whether to bypass the new site email notification. + * +@@ -942,9 +963,9 @@ + + // Send email with activation link. + if ( ! is_subdomain_install() || get_current_network_id() != 1 ) { +- $activate_url = network_site_url( "wp-activate.php?key=$key" ); ++ $activate_url = network_site_url( "wp-activate.php?key=$key&signup_id=$signup_id" ); + } else { +- $activate_url = "http://{$domain}{$path}wp-activate.php?key=$key"; // @todo Use *_url() API. ++ $activate_url = "http://{$domain}{$path}wp-activate.php?key=$key&signup_id=$signup_id"; // @todo use *_url() API + } + + $activate_url = esc_url( $activate_url ); +@@ -1055,9 +1076,10 @@ + * @param string $user_email The user's email address. + * @param string $key The activation key created in wpmu_signup_user() + * @param array $meta Optional. Signup meta data. Default empty array. ++ * @param int $signup_id Signup ID. + * @return bool + */ +-function wpmu_signup_user_notification( $user_login, $user_email, $key, $meta = array() ) { ++function wpmu_signup_user_notification( $user_login, $user_email, $key, $meta = array(), $signup_id ) { + /** + * Filters whether to bypass the email notification for new user sign-up. + * +@@ -1107,7 +1129,7 @@ + $key, + $meta + ), +- site_url( "wp-activate.php?key=$key" ) ++ site_url( "wp-activate.php?key=$key&signup_id=$signup_id" ) + ); + + $subject = sprintf( +@@ -1157,17 +1179,53 @@ + * @global wpdb $wpdb WordPress database abstraction object. + * + * @param string $key The activation key provided to the user. ++ * @param int $signup_id The Signup ID. + * @return array|WP_Error An array containing information about the activated user and/or blog. + */ +-function wpmu_activate_signup( $key ) { +- global $wpdb; ++function wpmu_activate_signup( $key, $signup_id ) { ++ global $wpdb, $wp_hasher; + +- $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE activation_key = %s", $key ) ); ++ $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE activation_key = %s OR signup_id = %d", $key, $signup_id ) ); + + if ( empty( $signup ) ) { + return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) ); + } + ++ // If the key requested matches the actual key in the database, it's a legacy one. ++ if ( $key === $signup->activation_key ) { ++ return new WP_Error( 'expired_key', __( 'Invalid key' ) ); ++ } ++ ++ // The format of the new keys is <timestamp>:<hashed_key>. ++ if ( false === strpos( $signup->activation_key, ':' ) ) { ++ return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) ); ++ } ++ ++ if ( empty( $wp_hasher ) ) { ++ require_once ABSPATH . WPINC . '/class-phpass.php'; ++ $wp_hasher = new PasswordHash( 8, true ); ++ } ++ ++ list( $pass_request_time, $signup_key ) = explode( ':', $signup->activation_key, 2 ); ++ ++ if ( ! $wp_hasher->CheckPassword( $key, $signup_key ) ) { ++ return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) ); ++ } ++ ++ /** ++ * Filters the expiration time of signup activation keys. ++ * ++ * @since 5.0 ++ * ++ * @param int $expiration_duration The expiration time in seconds. ++ */ ++ $expiration_duration = apply_filters( 'activate_signup_expiration', DAY_IN_SECONDS ); ++ $expiration_time = $pass_request_time + $expiration_duration; ++ ++ if ( time() > $expiration_time ) { ++ return new WP_Error( 'expired_key', __( 'Invalid key' ) ); ++ } ++ + if ( $signup->active ) { + if ( empty( $signup->domain ) ) { + return new WP_Error( 'already_active', __( 'The user is already active.' ), $signup ); |