Make WordPress Core


Ignore:
Timestamp:
11/09/2021 10:37:19 PM (5 years ago)
Author:
hellofromTonya
Message:

HTTP API: Introduce 'http_allowed_safe_ports' filter in wp_http_validate_url().

Adds a new filter 'http_allowed_safe_ports' to control which ports are allowed for remote requests. By default, ports 80, 443, and 8080 are allowed for safe remote requests.

Adds tests.

Follow-up to [24480].

Props xknown, johnbillion, jorbin, costdev, dd32.
Fixes #54331.

File:
1 edited

Legend:

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

    r52010 r52084  
    393393        }
    394394
     395        /**
     396         * Test that wp_http_validate_url validates URLs.
     397         *
     398         * @ticket 54331
     399         *
     400         * @dataProvider data_wp_http_validate_url_should_validate
     401         *
     402         * @covers ::wp_http_validate_url
     403         *
     404         * @param string       $url            The URL to validate.
     405         * @param false|string $cb_safe_ports  The name of the callback to http_allowed_safe_ports or false if none.
     406         *                                     Default false.
     407         * @param bool         $external_host  Whether or not the host is external.
     408         *                                     Default false.
     409         */
     410        public function test_wp_http_validate_url_should_validate( $url, $cb_safe_ports = false, $external_host = false ) {
     411                if ( $external_host ) {
     412                        add_filter( 'http_request_host_is_external', '__return_true' );
     413                }
     414
     415                if ( $cb_safe_ports ) {
     416                        add_filter( 'http_allowed_safe_ports', array( $this, $cb_safe_ports ) );
     417                }
     418
     419                $this->assertSame( $url, wp_http_validate_url( $url ) );
     420        }
     421
     422        /**
     423         * Data provider.
     424         *
     425         * @return array
     426         */
     427        public function data_wp_http_validate_url_should_validate() {
     428                return array(
     429                        'no port specified'                 => array(
     430                                'url' => 'http://example.com/caniload.php',
     431                        ),
     432                        'an external request when allowed'  => array(
     433                                'url'           => 'http://172.20.0.123/caniload.php',
     434                                'cb_safe_ports' => false,
     435                                'external_host' => true,
     436                        ),
     437                        'a port considered safe by default' => array(
     438                                'url' => 'https://example.com:8080/caniload.php',
     439                        ),
     440                        'a port considered safe by filter'  => array(
     441                                'url'           => 'https://example.com:81/caniload.php',
     442                                'cb_safe_ports' => 'callback_custom_safe_ports',
     443                        ),
     444                );
     445        }
     446
     447        /**
     448         * Tests that wp_http_validate_url validates a url that uses an unsafe port
     449         * but which matches the host and port used by the site's home url.
     450         *
     451         * @ticket 54331
     452         *
     453         * @covers ::wp_http_validate_url
     454         */
     455        public function test_wp_http_validate_url_should_validate_with_an_unsafe_port_when_the_host_and_port_match_the_home_url() {
     456                $original_home    = get_option( 'home' );
     457                $home_parsed      = parse_url( $original_home );
     458                $home_scheme_host = implode( '://', array_slice( $home_parsed, 0, 2 ) );
     459                $home_modified    = $home_scheme_host . ':83';
     460
     461                update_option( 'home', $home_modified );
     462
     463                $url = $home_modified . '/caniload.php';
     464                $this->assertSame( $url, wp_http_validate_url( $url ) );
     465
     466                update_option( 'home', $original_home );
     467        }
     468
     469        /**
     470         * Test that wp_http_validate_url does not validate invalid URLs.
     471         *
     472         * @ticket 54331
     473         *
     474         * @dataProvider data_wp_http_validate_url_should_not_validate
     475         *
     476         * @covers ::wp_http_validate_url
     477         *
     478         * @param string       $url            The URL to validate.
     479         * @param false|string $cb_safe_ports  The name of the callback to http_allowed_safe_ports or false if none.
     480         *                                     Default false.
     481         * @param bool         $external_host  Whether or not the host is external.
     482         *                                     Default false.
     483         */
     484        public function test_wp_http_validate_url_should_not_validate( $url, $cb_safe_ports = false, $external_host = false ) {
     485                if ( $external_host ) {
     486                        add_filter( 'http_request_host_is_external', '__return_true' );
     487                }
     488
     489                if ( $cb_safe_ports ) {
     490                        add_filter( 'http_allowed_safe_ports', array( $this, $cb_safe_ports ) );
     491                }
     492
     493                $this->assertFalse( wp_http_validate_url( $url ) );
     494        }
     495
     496        /**
     497         * Data provider.
     498         *
     499         * @return array
     500         */
     501        public function data_wp_http_validate_url_should_not_validate() {
     502                return array(
     503                        'url as false'                                 => array(
     504                                'url' => false,
     505                        ),
     506                        'url as null'                                  => array(
     507                                'url' => null,
     508                        ),
     509                        'url as int 0'                                 => array(
     510                                'url' => 0,
     511                        ),
     512                        'url as string 0'                              => array(
     513                                'url' => '0',
     514                        ),
     515                        'url as int 1'                                 => array(
     516                                'url' => 1,
     517                        ),
     518                        'url as string 1'                              => array(
     519                                'url' => '1',
     520                        ),
     521                        'url as array()'                               => array(
     522                                'url' => array(),
     523                        ),
     524                        'an empty url'                                 => array(
     525                                'url' => '',
     526                        ),
     527                        'a url with a non-http/https protocol'         => array(
     528                                'url' => 'ftp://example.com:81/caniload.php',
     529                        ),
     530                        'a malformed url'                              => array(
     531                                'url' => 'http:///example.com:81/caniload.php',
     532                        ),
     533                        'a host that cannot be parsed'                 => array(
     534                                'url' => 'http:example.com/caniload.php',
     535                        ),
     536                        'login information'                            => array(
     537                                'url' => 'http://user:pass@example.com/caniload.php',
     538                        ),
     539                        'a host with invalid characters'               => array(
     540                                'url' => 'http://[exam]ple.com/caniload.php',
     541                        ),
     542                        'a host whose IPv4 address cannot be resolved' => array(
     543                                'url' => 'http://exampleeeee.com/caniload.php',
     544                        ),
     545                        'an external request when not allowed'         => array(
     546                                'url'           => 'http://192.168.0.1/caniload.php',
     547                                'external_host' => false,
     548                        ),
     549                        'a port not considered safe by default'        => array(
     550                                'url' => 'https://example.com:81/caniload.php',
     551                        ),
     552                        'a port not considered safe by filter'         => array(
     553                                'url'           => 'https://example.com:82/caniload.php',
     554                                'cb_safe_ports' => 'callback_custom_safe_ports',
     555                        ),
     556                        'all safe ports removed by filter'             => array(
     557                                'url'           => 'https://example.com:81/caniload.php',
     558                                'cb_safe_ports' => 'callback_remove_safe_ports',
     559                        ),
     560                );
     561        }
     562
     563        public function callback_custom_safe_ports( $ports ) {
     564                return array( 81, 444, 8081 );
     565        }
     566
     567        public function callback_remove_safe_ports( $ports ) {
     568                return array();
     569        }
    395570}
Note: See TracChangeset for help on using the changeset viewer.