From 15315e51a4fbd087857a4572e2c48f52134171eb Mon Sep 17 00:00:00 2001
From: Jake Spurlock <whyisjake@git.wordpress.org>
Date: Mon, 14 Oct 2019 19:01:10 +0000
Subject: [PATCH] Backporting several bug fixes.

- Query: Remove the static query property.
- HTTP API: Protect against hex interpretation.
- Filesystem API: Prevent directory travelersals when creating new folders.
- Administration: Ensure that admin referer nonce is valid.
- REST API: Send a Vary: Origin header on GET requests.

Backports [46474], [46475], [46476], [46477], [46478], [46483], [46485] to the 4.6 branch.


git-svn-id: https://develop.svn.wordpress.org/branches/4.6@46496 602fd350-edb4-49c9-b593-d223f7449a82
---
 src/wp-includes/class-wp.php       |   2 +-
 src/wp-includes/functions.php      |   5 ++
 src/wp-includes/http.php           |   5 +-
 src/wp-includes/pluggable.php      |   8 ++-
 src/wp-includes/query.php          |   3 +-
 src/wp-includes/rest-api.php       |   3 +
 src/wp-includes/theme.php          |   2 +-
 tests/phpunit/tests/auth.php       |  37 ++++++++++
 tests/phpunit/tests/query/vars.php | 107 +++++++++++++++--------------
 9 files changed, 111 insertions(+), 61 deletions(-)

diff --git a/src/wp-includes/class-wp.php b/src/wp-includes/class-wp.php
index b363e2d444..46d57e2a50 100644
--- a/src/wp-includes/class-wp.php
+++ b/src/wp-includes/class-wp.php
@@ -15,7 +15,7 @@ class WP {
 	 * @access public
 	 * @var array
 	 */
-	public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'embed' );
+	public $public_query_vars = array( 'm', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'pagename', 'page_id', 'error', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'embed' );
 
 	/**
 	 * Private query variables.
diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
index e596f62a12..1456e18fe9 100644
--- a/src/wp-includes/functions.php
+++ b/src/wp-includes/functions.php
@@ -1611,6 +1611,11 @@ function wp_mkdir_p( $target ) {
 	if ( file_exists( $target ) )
 		return @is_dir( $target );
 
+	// Do not allow path traversals.
+	if ( false !== strpos( $target, '../' ) || false !== strpos( $target, '..' . DIRECTORY_SEPARATOR ) ) {
+		return false;
+	}
+
 	// We need to find the permissions of the parent folder that exists and inherit that.
 	$target_parent = dirname( $target );
 	while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
diff --git a/src/wp-includes/http.php b/src/wp-includes/http.php
index 23f322df2e..1652bbcc48 100644
--- a/src/wp-includes/http.php
+++ b/src/wp-includes/http.php
@@ -538,8 +538,9 @@ function wp_http_validate_url( $url ) {
 			$ip = $host;
 		} else {
 			$ip = gethostbyname( $host );
-			if ( $ip === $host ) // Error condition for gethostbyname()
-				$ip = false;
+			if ( $ip === $host ) { // Error condition for gethostbyname()
+				return false;
+			}
 		}
 		if ( $ip ) {
 			$parts = array_map( 'intval', explode( '.', $ip ) );
diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php
index 3c3d2232ad..a6a9e316bc 100644
--- a/src/wp-includes/pluggable.php
+++ b/src/wp-includes/pluggable.php
@@ -1038,7 +1038,7 @@ if ( !function_exists('check_admin_referer') ) :
  *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
  */
 function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
-	if ( -1 == $action )
+	if ( -1 === $action )
 		_doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
 
 	$adminurl = strtolower(admin_url());
@@ -1056,7 +1056,7 @@ function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
 	 */
 	do_action( 'check_admin_referer', $action, $result );
 
-	if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
+	if ( ! $result && ! ( -1 === $action && strpos( $referer, $adminurl ) === 0 ) ) {
 		wp_nonce_ays( $action );
 		die();
 	}
@@ -1081,6 +1081,9 @@ if ( !function_exists('check_ajax_referer') ) :
  *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
  */
 function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
+	if ( -1 === $action )
+		_doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
+
 	$nonce = '';
 
 	if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) )
@@ -2459,4 +2462,3 @@ function wp_text_diff( $left_string, $right_string, $args = null ) {
 	return $r;
 }
 endif;
-
diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php
index 053bd4cac3..24531ce35e 100644
--- a/src/wp-includes/query.php
+++ b/src/wp-includes/query.php
@@ -1416,7 +1416,6 @@ class WP_Query {
 			, 'attachment'
 			, 'attachment_id'
 			, 'name'
-			, 'static'
 			, 'pagename'
 			, 'page_id'
 			, 'second'
@@ -1637,7 +1636,7 @@ class WP_Query {
 			// If year, month, day, hour, minute, and second are set, a single
 			// post is being queried.
 			$this->is_single = true;
-		} elseif ( '' != $qv['static'] || '' != $qv['pagename'] || !empty($qv['page_id']) ) {
+		} elseif ( '' != $qv['pagename'] || !empty($qv['page_id']) ) {
 			$this->is_page = true;
 			$this->is_single = false;
 		} else {
diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
index 13bfa596ec..003a71ac1b 100644
--- a/src/wp-includes/rest-api.php
+++ b/src/wp-includes/rest-api.php
@@ -395,6 +395,9 @@ function rest_send_cors_headers( $value ) {
 		header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
 		header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' );
 		header( 'Access-Control-Allow-Credentials: true' );
+		header( 'Vary: Origin', false );
+	} elseif ( ! headers_sent() && 'GET' === $_SERVER['REQUEST_METHOD'] && ! is_user_logged_in() ) {
+		header( 'Vary: Origin', false );
 	}
 
 	return $value;
diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php
index e71e417e16..ff55af99ed 100644
--- a/src/wp-includes/theme.php
+++ b/src/wp-includes/theme.php
@@ -1374,7 +1374,7 @@ function _custom_background_cb() {
 	$style = $color ? "background-color: #$color;" : '';
 
 	if ( $background ) {
-		$image = " background-image: url('$background');";
+		$image = " background-image: url('" . esc_url_raw( $background ) . "');";
 
 		$repeat = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) );
 		if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
diff --git a/tests/phpunit/tests/auth.php b/tests/phpunit/tests/auth.php
index ea696a6967..5b8ff8e7d3 100644
--- a/tests/phpunit/tests/auth.php
+++ b/tests/phpunit/tests/auth.php
@@ -153,6 +153,43 @@ class Tests_Auth extends WP_UnitTestCase {
 		$this->assertEquals( $count, did_action( $this->nonce_failure_hook ) );
 	}
 
+	/**
+	 * @ticket 36361
+	 */
+	public function test_check_admin_referer_with_no_action_triggers_doing_it_wrong() {
+		$this->setExpectedIncorrectUsage( 'check_admin_referer' );
+
+		// A valid nonce needs to be set so the check doesn't die()
+		$_REQUEST['_wpnonce'] = wp_create_nonce( -1 );
+		$result = check_admin_referer();
+		$this->assertSame( 1, $result );
+
+		unset( $_REQUEST['_wpnonce'] );
+	}
+
+	public function test_check_admin_referer_with_default_action_as_string_not_doing_it_wrong() {
+		// A valid nonce needs to be set so the check doesn't die()
+		$_REQUEST['_wpnonce'] = wp_create_nonce( '-1' );
+		$result               = check_admin_referer( '-1' );
+		$this->assertSame( 1, $result );
+
+		unset( $_REQUEST['_wpnonce'] );
+	}
+
+	/**
+	 * @ticket 36361
+	 */
+	public function test_check_ajax_referer_with_no_action_triggers_doing_it_wrong() {
+		$this->setExpectedIncorrectUsage( 'check_ajax_referer' );
+
+		// A valid nonce needs to be set so the check doesn't die()
+		$_REQUEST['_wpnonce'] = wp_create_nonce( -1 );
+		$result = check_ajax_referer();
+		$this->assertSame( 1, $result );
+
+		unset( $_REQUEST['_wpnonce'] );
+	}
+
 	function test_password_length_limit() {
 		$limit = str_repeat( 'a', 4096 );
 
diff --git a/tests/phpunit/tests/query/vars.php b/tests/phpunit/tests/query/vars.php
index 758fb86580..705d3852b9 100644
--- a/tests/phpunit/tests/query/vars.php
+++ b/tests/phpunit/tests/query/vars.php
@@ -16,61 +16,64 @@ class Tests_Query_Vars extends WP_UnitTestCase {
 		// Re-initialise any dynamically-added public query vars:
 		do_action( 'init' );
 
-		$this->assertEquals( array(
+		$this->assertEquals(
+			array(
 
-			// Static public query vars:
-			'm',
-			'p',
-			'posts',
-			'w',
-			'cat',
-			'withcomments',
-			'withoutcomments',
-			's',
-			'search',
-			'exact',
-			'sentence',
-			'calendar',
-			'page',
-			'paged',
-			'more',
-			'tb',
-			'pb',
-			'author',
-			'order',
-			'orderby',
-			'year',
-			'monthnum',
-			'day',
-			'hour',
-			'minute',
-			'second',
-			'name',
-			'category_name',
-			'tag',
-			'feed',
-			'author_name',
-			'static',
-			'pagename',
-			'page_id',
-			'error',
-			'attachment',
-			'attachment_id',
-			'subpost',
-			'subpost_id',
-			'preview',
-			'robots',
-			'taxonomy',
-			'term',
-			'cpage',
-			'post_type',
-			'embed',
+				// Static public query vars:
+				'm',
+				'p',
+				'posts',
+				'w',
+				'cat',
+				'withcomments',
+				'withoutcomments',
+				's',
+				'search',
+				'exact',
+				'sentence',
+				'calendar',
+				'page',
+				'paged',
+				'more',
+				'tb',
+				'pb',
+				'author',
+				'order',
+				'orderby',
+				'year',
+				'monthnum',
+				'day',
+				'hour',
+				'minute',
+				'second',
+				'name',
+				'category_name',
+				'tag',
+				'feed',
+				'author_name',
+				'pagename',
+				'page_id',
+				'error',
+				'attachment',
+				'attachment_id',
+				'subpost',
+				'subpost_id',
+				'preview',
+				'robots',
+				'taxonomy',
+				'term',
+				'cpage',
+				'post_type',
+				'embed',
 
-			// Dynamically added public query vars:
-			'post_format',
-			'rest_route',
+				// Dynamically added public query vars:
+				'post_format',
+				'rest_route',
 
-		), $wp->public_query_vars, 'Care should be taken when introducing new public query vars. See https://core.trac.wordpress.org/ticket/35115' );
+			),
+			$wp->public_query_vars,
+			'Care should be taken when introducing new public query vars. See https://core.trac.wordpress.org/ticket/35115'
+		);
 	}
 
 }