Make WordPress Core

Changeset 56844 for branches/6.3


Ignore:
Timestamp:
10/12/2023 01:24:56 PM (14 months ago)
Author:
audrasjb
Message:

Application Passwords: Prevent the use of some pseudo protocols in application passwords.

Props tykoted, xknown, peterwilsoncc, jorbin, timothyblynjacobs, martinkrcho, paulkevan, dd32, ehtis.
Merges [56837] to the 6.3 branch.

Location:
branches/6.3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/6.3

  • branches/6.3/src/wp-admin/includes/user.php

    r55988 r56844  
    637637 * @since 5.6.0
    638638 * @since 6.2.0 Allow insecure HTTP connections for the local environment.
     639 * @since 6.3.2 Validates the success and reject URLs to prevent javascript pseudo protocol being executed.
    639640 *
    640641 * @param array   $request {
     
    650651 */
    651652function wp_is_authorize_application_password_request_valid( $request, $user ) {
    652     $error    = new WP_Error();
    653     $is_local = 'local' === wp_get_environment_type();
    654 
    655     if ( ! empty( $request['success_url'] ) ) {
    656         $scheme = wp_parse_url( $request['success_url'], PHP_URL_SCHEME );
    657 
    658         if ( 'http' === $scheme && ! $is_local ) {
     653    $error = new WP_Error();
     654
     655    if ( isset( $request['success_url'] ) ) {
     656        $validated_success_url = wp_is_authorize_application_redirect_url_valid( $request['success_url'] );
     657        if ( is_wp_error( $validated_success_url ) ) {
    659658            $error->add(
    660                 'invalid_redirect_scheme',
    661                 __( 'The success URL must be served over a secure connection.' )
     659                $validated_success_url->get_error_code(),
     660                $validated_success_url->get_error_message()
    662661            );
    663662        }
    664663    }
    665664
    666     if ( ! empty( $request['reject_url'] ) ) {
    667         $scheme = wp_parse_url( $request['reject_url'], PHP_URL_SCHEME );
    668 
    669         if ( 'http' === $scheme && ! $is_local ) {
     665    if ( isset( $request['reject_url'] ) ) {
     666        $validated_reject_url = wp_is_authorize_application_redirect_url_valid( $request['reject_url'] );
     667        if ( is_wp_error( $validated_reject_url ) ) {
    670668            $error->add(
    671                 'invalid_redirect_scheme',
    672                 __( 'The rejection URL must be served over a secure connection.' )
     669                $validated_reject_url->get_error_code(),
     670                $validated_reject_url->get_error_message()
    673671            );
    674672        }
     
    699697    return true;
    700698}
     699
     700/**
     701 * Validates the redirect URL protocol scheme. The protocol can be anything except http and javascript.
     702 *
     703 * @since 6.3.2
     704 *
     705 * @param string $url - The redirect URL to be validated.
     706 *
     707 * @return true|WP_Error True if the redirect URL is valid, a WP_Error object otherwise.
     708 */
     709function wp_is_authorize_application_redirect_url_valid( $url ) {
     710    $bad_protocols = array( 'javascript', 'data' );
     711    if ( empty( $url ) ) {
     712        return true;
     713    }
     714
     715    // Based on https://www.rfc-editor.org/rfc/rfc2396#section-3.1
     716    $valid_scheme_regex = '/^[a-zA-Z][a-zA-Z0-9+.-]*:/';
     717    if ( ! preg_match( $valid_scheme_regex, $url ) ) {
     718        return new WP_Error(
     719            'invalid_redirect_url_format',
     720            __( 'Invalid URL format.' )
     721        );
     722    }
     723
     724    /**
     725     * Filters the list of invalid protocols used in applications redirect URLs.
     726     *
     727     * @since 6.3.2
     728     *
     729     * @param string[]  $bad_protocols Array of invalid protocols.
     730     * @param string    $url The redirect URL to be validated.
     731     */
     732    $invalid_protocols = array_map( 'strtolower', apply_filters( 'wp_authorize_application_redirect_url_invalid_protocols', $bad_protocols, $url ) );
     733
     734    $scheme   = wp_parse_url( $url, PHP_URL_SCHEME );
     735    $host     = wp_parse_url( $url, PHP_URL_HOST );
     736    $is_local = 'local' === wp_get_environment_type();
     737
     738    // validates if the proper URI format is applied to the $url
     739    if ( empty( $host ) || empty( $scheme ) || in_array( strtolower( $scheme ), $invalid_protocols, true ) ) {
     740        return new WP_Error(
     741            'invalid_redirect_url_format',
     742            __( 'Invalid URL format.' )
     743        );
     744    }
     745
     746    if ( 'http' === $scheme && ! $is_local ) {
     747        return new WP_Error(
     748            'invalid_redirect_scheme',
     749            __( 'The URL must be served over a secure connection.' )
     750        );
     751    }
     752
     753    return true;
     754}
Note: See TracChangeset for help on using the changeset viewer.