Make WordPress Core

Changeset 56837


Ignore:
Timestamp:
10/12/2023 12:39:18 PM (3 years ago)
Author:
jorbin
Message:

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

Props tykoted, xknown, peterwilsoncc, jorbin, timothyblynjacobs, martinkrcho, paulkevan, dd32, ehtis.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/user.php

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