Additional checks when evaluating the safety of an HTTP request, to avoid false negatives.

* Check if the host is considered a safe redirect host.
 * Check if the host is another domain in a multisite installation.
 * Add a filter to control this.

This only occurs when the DNS resolution of a domain points elsewhere in an internal network, but only internally (and has its own public IP outside the network). This could be considered a bad configuration.

fixes #24646.



git-svn-id: http://core.svn.wordpress.org/trunk@24915 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2013-07-31 06:44:57 +00:00
parent 4833e3096b
commit 1ec392175c
3 changed files with 56 additions and 9 deletions

View File

@ -196,6 +196,8 @@ add_filter( 'nav_menu_meta_box_object', '_wp_nav_menu_meta_box_object' );
add_filter( 'pingback_ping_source_uri', 'pingback_ping_source_uri' ); add_filter( 'pingback_ping_source_uri', 'pingback_ping_source_uri' );
add_filter( 'xmlrpc_pingback_error', 'xmlrpc_pingback_error' ); add_filter( 'xmlrpc_pingback_error', 'xmlrpc_pingback_error' );
add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
// Actions // Actions
add_action( 'wp_head', 'wp_enqueue_scripts', 1 ); add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
add_action( 'wp_head', 'feed_links', 2 ); add_action( 'wp_head', 'feed_links', 2 );

View File

@ -451,17 +451,18 @@ function wp_http_validate_url( $url ) {
$ip = false; $ip = false;
} }
if ( $ip ) { if ( $ip ) {
if ( '127.0.0.1' === $ip )
return false;
$parts = array_map( 'intval', explode( '.', $ip ) ); $parts = array_map( 'intval', explode( '.', $ip ) );
if ( 10 === $parts[0] ) if ( '127.0.0.1' === $ip
return false; || ( 10 === $parts[0] )
if ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] ) || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
return false; || ( 192 === $parts[0] && 168 === $parts[1] )
if ( 192 === $parts[0] && 168 === $parts[1] ) ) {
// If host appears local, reject unless specifically allowed.
if ( ! apply_filters( 'http_request_host_is_external', false, $host, $url ) )
return false; return false;
} }
} }
}
if ( empty( $parsed_url['port'] ) ) if ( empty( $parsed_url['port'] ) )
return $url; return $url;
@ -475,3 +476,44 @@ function wp_http_validate_url( $url ) {
return false; return false;
} }
/**
* Whitelists allowed redirect hosts for safe HTTP requests as well.
*
* Attached to the http_request_host_is_external filter.
*
* @since 3.6.0
*
* @param bool $is_external
* @param string $host
* @return bool
*/
function allowed_http_request_hosts( $is_external, $host ) {
if ( ! $is_external && wp_validate_redirect( 'http://' . $host ) )
$is_external = true;
return $is_external;
}
/**
* Whitelists any domain in a multisite installation for safe HTTP requests.
*
* Attached to the http_request_host_is_external filter.
*
* @since 3.6.0
*
* @param bool $is_external
* @param string $host
* @return bool
*/
function ms_allowed_http_request_hosts( $is_external, $host ) {
global $wpdb, $current_site;
static $queried = array();
if ( $is_external )
return $is_external;
if ( $host === $current_site->domain )
return true;
if ( isset( $queried[ $host ] ) )
return $queried[ $host ];
$queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) );
return $queried[ $host ];
}

View File

@ -64,3 +64,6 @@ remove_filter( 'option_home', '_config_wp_home' );
// If the network upgrade hasn't run yet, assume ms-files.php rewriting is used. // If the network upgrade hasn't run yet, assume ms-files.php rewriting is used.
add_filter( 'default_site_option_ms_files_rewriting', '__return_true' ); add_filter( 'default_site_option_ms_files_rewriting', '__return_true' );
// Whitelist multisite domains for HTTP requests
add_filter( 'http_request_host_is_external', 'ms_allowed_http_request_hosts', 20, 2 );