CVE-2017-14723: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: Before version 4.8.2, WordPress mishandled % characters and additional placeholder values in $wpdb->prepare, and thus did not properly address the possibility of plugins and themes enabling SQL injection attacks.
CWE description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
CVSS v3 base score: 9.8
Published: 2017-09-23T20:29Z
Repository: https://github.com/WordPress/WordPress
Language: PHP
Files changed: wp-includes/version.php, wp-includes/wp-db.php
Commit date: 2017-09-19 14:48:47 +0000
Commit message: Database: Hardening for `wpdb::prepare()`

Previously if you passed an array of values for placeholders, additional values could be passed as well. Now additional values will be ignored.


Built from https://develop.svn.wordpress.org/trunk@41470


git-svn-id: http://core.svn.wordpress.org/trunk@41303 1a063a9b-81f0-0310-95a4-ce76da25c4cd

Diff: diff --git a/wp-includes/version.php b/wp-includes/version.php
index 6967ffd8b19..3e8480acf96 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -2,11 +2,11 @@
 /**
  * The WordPress version string
  *
  * @global string $wp_version
  */
-$wp_version = '4.9-alpha-41457';
+$wp_version = '4.9-alpha-41470';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
  *
  * @global int $wp_db_version
diff --git a/wp-includes/wp-db.php b/wp-includes/wp-db.php
index 57ed865a35a..5cc2be114fc 100644
--- a/wp-includes/wp-db.php
+++ b/wp-includes/wp-db.php
@@ -1234,13 +1234,22 @@ class wpdb {
 			_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9.0' );
 		}
 
 		$args = func_get_args();
 		array_shift( $args );
+
 		// If args were passed as an array (as in vsprintf), move them up
-		if ( isset( $args[0] ) && is_array($args[0]) )
+		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
 			$args = $args[0];
+		}
+
+		foreach ( $args as $arg ) {
+			if ( ! is_scalar( $arg ) ) {
+				_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' );
+			}
+		}
+
 		$query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
 		$query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
 		$query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
 		$query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
 		array_walk( $args, array( $this, 'escape_by_ref' ) );

Vulnerable code: $wp_version = '4.9-alpha-41457';
		if ( isset( $args[0] ) && is_array($args[0]) )
Fixed code: $wp_version = '4.9-alpha-41470';

		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
		}

		foreach ( $args as $arg ) {
			if ( ! is_scalar( $arg ) ) {
				_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' );
			}
		}